Skip to content

Comments

ST6RI-815 Variable Features (KERML_-57, SYSML2_-510)#637

Merged
seidewitz merged 82 commits intomasterfrom
ST6RI-815
Mar 26, 2025
Merged

ST6RI-815 Variable Features (KERML_-57, SYSML2_-510)#637
seidewitz merged 82 commits intomasterfrom
ST6RI-815

Conversation

@seidewitz
Copy link
Member

@seidewitz seidewitz commented Mar 22, 2025

This PR implements resolutions to the following issues, as approved in KerML FTF2 Ballot 5 and SysML v2 FTF 2 Ballot 7:

  • KERML_-57 Time and space life/slice/portion modeling patterns are missing
  • SYSML2_-510 Variable features for SysML

KerML

Semantics

The resolution to KERML_-57 introduces the concept of "variable features", which are features of occurrences whose values may vary over time. This is specified semantically by making the domain of a variable feature (i.e., its featuring type) the snapshots of its owning type, rather the owning type itself. Therefore, a variable feature can have different values on different snapshots of an occurrence, effectively "varying over time". The multiplicity of a variable feature is relative to each snapshot, rather than to the life of the occurrence.

Abstract Syntax

Updates to the abstract syntax to achieve these semantics include the following.

  1. Add property isVariable to Feature. (isReadonly is renamed to isConstant.)
  2. Remove the Featuring superclass of FeatureMembership and TypeFeaturing. Instead of FeatureMembership being a kind of Featuring, it implies TypeFeaturing in two different cases.
    • If isVariable = false, then FeatureMembership implies a TypeFeaturing relationship from its ownedMemberFeature to its owningType. This duplicates the current semantics for FeatureMembership.
    • If isVariable = true, then FeatureMembership implies a TypeFeaturing relationship from its ownedMemberFeature to a Feature representing the snapshots of its owningType. This Feature is an ownedRelatedElement of the implied TypeFeaturing, and it is constructed to redefine Occurrences::Occurrence::snapshots and be featured by the owningType of the FeatureMembership. This achieves the semantics of variable features.
  3. Add operation isCompatibleWith to Type and Feature. For a non-Feature Type, isCompatibleWith is the same as specializes. A Feature, however, isCompatibleWith another Feature not only if it specializes the other Feature, but also if the two Features have a common redefinedFeature and the first Feature is accessible from a featuringType of the other Feature. This allows the snapshots featuringType of one variable Feature to be considered to semantically specialize the similar featuringType of another variable Feature, for the purposes of validation, without there having to be an actual Specialization relationship between them.
  4. Add the following new validation constraints:
    • validateFeatureConstantIsVariable – A constant feature must be variable.
    • validateFeatureEndIsConstant – A variable end feature must be constant.
    • validateFeatureEndNoDirection – An end feature must have no direction.
    • validateFeatureEndNotDerivedAbstractCompositeOrPortion - An end feature must not be derived, abstract, composite or a portion.
    • validateFeatureIsVariable – A variable feature must be a feature of an occurrence type.
    • validateFeaturePortionNotVariable – A portion feature must not be variable.
    • validateSubsettingConstantConformance – A variable feature must be constant if it subsets a constant feature.
    • validateFeatureValueIsInitial – A feature must be variable to have an initial feature value.

Note

Problems found during implementation resulted in the following variations from the resolution to KERML_-57. These have been documented in issue KERML_-224, the resolution of which is currently under review by the KerML FTF2.

  1. validateSubsettingConstantConformance – Implemented the validation to apply only if the subsettedFeature is constant and the subsettingFeature is variable.
  2. validateSubsettingPortionConformance – Did not implement the validation.
  3. validateRedefinitionDirectionConformance – Revised the implementation so that, if the redefiningFeature is variable, its owningType is used instead of its featuringType.
  4. validateRedefinitionFeaturingType – Revised the implementation so that, if the redefiningType and/or the redefinedType are variable, then their owningType is used instead of their featuringTypes.

Concrete Syntax

A variable feature is notated in the concrete syntax using the new keyword var.

// An instance of a Vehicle is a Life by default.
struct Vehicle {
    // This feature has a single value for the Vehicle's life.
    // It is not a feature of its timeslices or snapshots.
    feature id : VehicleId [1];

    // This feature can have a different single value on each snapshot of a Vehicle.
    var mileage : Distance [1];
}

A feature that is specified as variable can, nevertheless, be further specified as constant using the keyword const (instead of var), meaning that it does not actually change its value over the duration of its featuring occurrence (this replaces the previous concept of readonly). This can be useful for asserting that a feature has values that are the same over only some of the time an occurrence exists, even though it could potentially vary at other times.

struct Vehicle {
    feature id : VehicleId [1];
    var mileage : Distance [1];

    portion parked :> timeSlices [*] {
        // When a Vehicle is parked, its mileage does not change.
        const :>> mileage;
    }
}

The end features of an association structure may also be declared as constant features by placing the keyword const before the keyword end. Whether or not an end feature is declared as constant, its value cannot change for the lifetime of an instance of the owning association structure. However, a constant end feature may subset or redefine a variable feature, while a regular end feature cannot.

struct AssetOwnershipRecord {
    var feature owner : LegalEntity [1];
    var feature ownedAsset : Asset [1];
}
assoc struct AssetOwnershipRelationship specializes AssetOwnershipRecord {
    const end feature redefines owner;
    const end feature redefines ownedAsset;
}

In addition, the required ordering of the prefix keywords on a feature is changed so that derived must appear before any of abstract, composite, portion, var, or const (but after any direction keyword).

Model Libraries

Semantic Model Library

  1. Remove all uses of the keyword readonly.
  2. Clocks – Add var to the declarations of Clock::currentTime and BasicClock::currentTime.
  3. Occurrences – Add a default value of self to Occurrence::portionOfLife.

SysML

Semantics

In SysML models, it is already expected that features of occurrences can change over time, particularly for structural occurrences like items and parts. For example, if a Vehicle is modeled as having an engine with multiplicity 1..1, then the expectation is that any individual Vehicle has exactly one engine at any point in time, but may have different engines over time. Therefore, the resolution to SYSML2_-510 makes a feature of an occurrence definition or usage automatically able to vary in time, except for the following kinds of features, which, instead, have values relative to the entire duration of the featuring occurrence:

  1. Time slices and snapshots, because they represent specific portions of the duration of their featuring occurrences.
  2. Bindings, because they reflect relationships that can hold across time.
  3. Successions, because they determine ordering of occurrences across time.
  4. Composite subactions, because their values and ordering across time are determined by succession relationships and other control constructs.

Abstract Syntax

Updates to the SysML abstract syntax in order to formalize these expected semantics include:

  1. Add the property mayTimeVary to Usage, redefining the property Feature::isVariable from KerML to make it derived. In this way, owned features of OccurrenceDefinitions and OccurrencesUsages will, when appropriate, automatically have the expected variable feature semantics, without it having to be explicitly declared by the modeler (as it is in KerML).
  2. Add the constraint checkUsageVariationUsageTypeFeaturing requiring that a variant usage have the same featuring types as an owning variation usage, which is particularly important if the owning usage may time vary.
  3. Add the constraint validateAssignmentActionUsage, requiring the target of an assignment action to be time-varying.

Concrete Syntax

Since whether a feature may time vary is determined automatically, there is no keyword in SysML corresponding to var in KerML. However, a feature that would otherwise be allowed to vary in time may be declared to nevertheless have a constant value using the constant keyword (which replaces the previous readonly keyword). Such a feature must have the same value over the entire duration of a featuring occurrence.

occurrence def Flight {
    ref part aircraft : Aircraft;
}
occurrence def ApprovedFlight :> Flight {
    // This redefines the aircraft feature so it is constant for
    // an entire ApprovedFlight.
    constant ref part approvedAircraft redefines aircraft;
}

The constant keyword cannot be used on an end feature in SysML. However, any end feature that has mayTimeVary = true is also required to automatically have isConstant = true.

As for KerML, the required ordering of the prefix keywords on a usage is changed so that derived must appear before any of abstract, variation, constant, or ref (but after any direction keyword).

Note

There is an inconsistency in the Beta 3 specification in which the textual notation grammar does not allow both the variation and constant keywords on a usage declaration, even though it is allowable in the abstract syntax and semantics for a usage to have isVariation = true and isConstant = true. This inconsistency is documented in issue SYSML2_-801, the resolution of which is currently under review by the SysML v2 FTF2. As proposed in this resolution, the implementation in this PR does allow a usage to be both a variation and a constant.

Model Libraries

Cause and Effect Domain Library

  1. CausationConnections – Add abstract constant to the declarations of Multicausation::causes and effects.
  2. CausationConnections – Change the end features of Causation (which are now automatically constant) to subset rather than redefine causes and effects.

seidewitz and others added 30 commits November 8, 2023 18:06
- Also moved clearing of caches to ElementUtil.transformAll.
- Changed messages in APIS_transfer_interface into flows, because
messages between interface end ports was semantically incorrect and now
violated validateSubsettingConstantConformance.
- Also updated for proper KerML and SysML keywords.
- Results in no actual change to SysML.sysml over updates already done
for ST6RI-827.
- Removes need to clear caches for distinguishibility check.
@seidewitz seidewitz self-assigned this Mar 22, 2025
@seidewitz seidewitz requested review from TheKorpos and himi March 22, 2025 21:49
@seidewitz seidewitz added this to the 2025-02 milestone Mar 22, 2025
@himi
Copy link
Member

himi commented Mar 23, 2025

I started my review and I found the example below got an error of "Cannot override a binding feature value." Is that correct validation? Note that the error disappeared when :=5 was removed.

package ST6R815 {
	struct Vehicle {
		var milage := 5;
	}
	feature v : Vehicle {
		const :>> milage = 5;
	}
}

@himi
Copy link
Member

himi commented Mar 23, 2025

Also I felt strange that the example below was not marked as an error:

	struct Vehicle {
		const milage := 5;
	}

while

	struct Vehicle {
		milage := 5;
	}

gets an error of "Initialized feature must be variable."

@seidewitz
Copy link
Member Author

started my review and I found the example below got an error of "Cannot override a binding feature value." Is that correct validation? Note that the error disappeared when :=5 was removed.

This is correct. This is an existing validation that is not actually changed by this PR: A non-default feature value cannot be overridden, whether it is initial or not. The validation check does check to see if the overriding value is consistent with the original value, because this would, in general, require arbitrary expression computation -- i.e., it could not generally be checked statically.

@seidewitz
Copy link
Member Author

Also I felt strange that the example below was not marked as an error:

	struct Vehicle {
		const milage := 5;
	}

while

	struct Vehicle {
		milage := 5;
	}

gets an error of "Initialized feature must be variable."

This is also correct. A non-variable feature is not the same as a constant feature.

Odd as it may seem, any feature with isConstant = true must also have isVariable = true. That is, a feature can't be declared "constant" unless it first has a snapshots as its featuring type, so it would otherwise have been able to vary if not declared constant. Therefore, a constant feature can be initialized, but then it should just never change from that initial value.

On the other hand, a feature that is not variable cannot have an "initial" value. This is because the semantics of "initial value" is that it is the value of the feature on the starting snapshot of its owning type. So, for this to make sense, the feature must have snapshots as its featuring type -- that is, it must be variable.

@himi
Copy link
Member

himi commented Mar 23, 2025

Thank you. So in my understanding, const or var may have temporal semantics in the sense of 4D but without either (by default), we are not allowed to give any temporal semantics, and such temporal semantics are totally different from the concept of typical programming language of mutations. That is fair by itself. My remaining concern is that it would be quite confusing for typical programmers (especially who know JavaScript/TypeScript) since these are the same keywords.

@himi
Copy link
Member

himi commented Mar 23, 2025

I think I tested most of the pattern. May I ask one more question? Currently we do not get an error with the example below. I think it is not semantically correct but the current validator does not check it. Is that a correct understanding?

	part p1 {
		constant attribute a1 default:= 4;
		snapshot {
			constant attribute :>> a1 = 3; 
		}
	}

@seidewitz
Copy link
Member Author

seidewitz commented Mar 23, 2025

Thank you. So in my understanding, const or var may have temporal semantics in the sense of 4D but without either (by default), we are not allowed to give any temporal semantics, and such temporal semantics are totally different from the concept of typical programming language of mutations. That is fair by itself. My remaining concern is that it would be quite confusing for typical programmers (especially who know JavaScript/TypeScript) since these are the same keywords.

I am afraid I really don't understand your description of your understanding. Indeed, the temporal semantics of var and const are, by intent, just about like what would be expected by a programmer for variables and constants. What is different are the 4D semantics of features that are not var or const. But this is because KerML is a modeling language, not a programming language, and the 4D semantics are necessary to be able to declaratively define both temporal and spatial constraints.

But, also by intent, this is all largely hidden for SysML modelers, for which temporal modeling remains intuitively much like it was in SysML v1 and UML. The compromise is that SysML modelers then have to largely use constructs formally specified at the KerML level to model temporal relationships (like succession, etc.).

@seidewitz
Copy link
Member Author

I think I tested most of the pattern. May I ask one more question? Currently we do not get an error with the example below. I think it is not semantically correct but the current validator does not check it. Is that a correct understanding?

	part p1 {
		constant attribute a1 default:= 4;
		snapshot {
			constant attribute :>> a1 = 3; 
		}
	}

Yes, the current validation is simply that a default feature value can be overridden, but a non-default one cannot. Now, the time of the snapshot in your model is not given, it is possible that it is the start snapshot, in which case it would override the default without any semantic inconsistency. Or it could be generally deduced that the the declaration in the snapshot implies that the attribute has to have value 3 for all other snapshots, too, overriding the default.

But, really, this is again something that probably will have to be detected at "run time". I think we will need to work it out as we complete the description of execution semantics.

@himi
Copy link
Member

himi commented Mar 24, 2025

I am afraid I really don't understand your description of your understanding. Indeed, the temporal semantics of var and const are, but intent, just about like what would be expected by a programmer for variables and constants. What is different are the 4D semantics of features that are not var or const. But this is because KerML is a modeling language, not a programming language, and the 4D semantics are necessary to be able to declaratively define both temporal and spatial constraints.

I think I understand your intent. I agree that KerML is a modeling language and more or less is designed to capture the meta level of execution semantics, in contrast, the typical programming languages represent executions themselves. Still, var or const reminds typical programmers of the concept of mutable or immutable variables, which are different from 4D semantics.

But, also by intent, this is all largely hidden for SysML modelers, for which temporal modeling remains intuitively much like it was in SysML v1 and UML. The compromise is that SysML modelers then have to largely use constructs formally specified at the KerML level to model temporal relationships (like succession, etc.).

I agree on this. Typical users do not need to care about these because they exist only in KerML.

@himi
Copy link
Member

himi commented Mar 24, 2025

Yes, the current validation is simply that a default feature value can be overridden, but a non-default one cannot. Now, the time of the snapshot in your model is not given, it is possible that it is the start snapshot, in which case it would override the default without any semantic inconsistency. Or it could be generally deduced that the the declaration in the snapshot implies that the attribute has to have value 3 for all other snapshots, too, overriding the default.

But, really, this is again something that probably will have to be detected at "run time". I think we will need to work it out as we complete the description of execution semantics.

Thank you for your answer. That helps me a lot to understand it.

Copy link
Contributor

@TheKorpos TheKorpos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done some testing in Eclipse and everything seems to work as described. I've taken a glance at the code too. Apart from two super minor typos everything looks good.

@seidewitz
Copy link
Member Author

@TheKorpos
I am having trouble merging this branch. To resolve the merge conflicts, the SysML parser needs to be regenerated. However, I cannot get that to complete without Java heap space out-of-memory errors.

The problem is not with this branch, because I can't regenerate the SysML parser on master, either. The problem seems to come from the addition of the optional global qualification to qualified names on branch ST6RI-830. Commit c15a0d7 says that you "Re-generated sysml xtext infrastructure". But, if I check out that commit, I cannot reproduce the generation -- I get an out-of-memory error (and strange grammar warning messages). I have tried increasing the heap space considerably, with no luck.

Did you have to do anything special to get the SysML parser generation to complete? Are you able to regenerate the parser on master? Note that the problem isn't the parser splitter, because your "count" update is in place (and, anyway, the error seems to happen before the splitting).

@TheKorpos
Copy link
Contributor

TheKorpos commented Mar 26, 2025

Did you have to do anything special to get the SysML parser generation to complete? Are you able to regenerate the parser on master? Note that the problem isn't the parser splitter, because your "count" update is in place (and, anyway, the error seems to happen before the splitting).

@seidewitz
Yes, I totally forgot that we had to increase the maximum heap size in the Generate SysML (sysml) Language Infrastructure runconfig (arguments > vm arguments) to get it working. It was working with 16 gig but maybe it works with less too.

Update: master works with 10gigs

@seidewitz
Copy link
Member Author

Did you have to do anything special to get the SysML parser generation to complete? Are you able to regenerate the parser on master? Note that the problem isn't the parser splitter, because your "count" update is in place (and, anyway, the error seems to happen before the splitting).

@seidewitz Yes, I totally forgot that we had to increase the maximum heap size in the Generate SysML (sysml) Language Infrastructure runconfig (arguments > vm arguments) to get it working. It was working with 16 gig but maybe it works with less too.

Update: master works with 10gigs

I had previously only tried up to 8G. Before I saw your update, I got it to work with 12G.

This grammar is really getting out of hand, but w can go with this for now!

@seidewitz seidewitz merged commit 798f141 into master Mar 26, 2025
1 check passed
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.

5 participants