In the design of UML state charts it appears that I can chose to use either triggers or guard logic to achieve transitions between states.
So which is better to use? Given the same logic for transition, does a trigger behave any differently than a guard? What are the benefits/drawbacks of one over the other?
Are there perhaps differences depending on the particular tool, or does the UML standard strictly define the behaviors of either method of transition?
I'm presently using Simulink Stateflow to design a state machine.
Those two are different concepts.
Trigger is an event occurrence which enables the transition,
while guard is a condition that must be evaluated to true in order for the transition to proceed.
So you cannot use them interchangeably — they have different roles.
Also note that the default guard (if none is specified) is [true], so the trigger is often sufficient to move from one state to another.
Update:
Summary:
Trigger (event) is some new data (of any data type) that was received by the object.
Guard is boolean expression on some data that is alrady present in the object.
Trigger (event) is an outside event that some other actor fired - user has pressed a button, browser requested a page load, etc. So in the image above, every time user presses a digit on a digital lock it fires "pressed digit" event.
If the pin (sequence of digits) is valid, then the transition to unlocked state will be enabled.
Yet another way to look at it:
If you press a keyboard key the system fires a keypress event, that would be a trigger whose value is the pressed key. Then you can make a guard [pressedKey = enter] (guard is always a boolean expression).
However having just the guard is not enough here, because there would be nothing to compare against.
Strictly speaking, guards cannot be used without triggers.
UML 2.5.1 specification (Section 14.2.4.8, page 331) defines State Machine's transitions by the following BNF expression:
[<trigger> [‘,’ <trigger>]* [‘[‘ <guard>’]’] [‘/’ <behavior-expression>]]
While UML 2.0 defined them as:
<transition> ::= <trigger> [‘,’ <trigger>]* [‘[‘ <guard-constraint>’]’] [‘/’ <activity-expression>]
Triggers are defined as:
<trigger> ::= <call-event> | <signal-event> | <any-receive-event> | <time-event> | <change-event>
So, in both cases, there cannot be a transition with a guard that doesn't have any trigger.
The only exception, according to UML 2.5.1, are internal transitions, which are specified by:
{<trigger>}* ['[' <guard>']'] [/<behavior-expression>]
Related
I'm having an issue where a rule isn't updating state and firing when it shouldn't I only want the rule to fire when both switches are open.
For example:
In the following order I
open switcha
close switcha
open switchb
It fires the rule, when it shouldn't as switcha is closed. It appears as soon as
Switch( name == "switcha", status == "Open ) becomes true, it holds this state even when closing the switch again.
rule "Electrical Circuit Status"
when
Switch( name == "switcha", status == "Open" )
and
Switch( name == "switchb", status == "Open" )
then // Raise Alert
** Didn't write this code out as it works fine
end
I appreciate any help.
You're likely misunderstanding working memory state. However since your question is extremely light on details, I'm going to make several assumptions in my explanation which I'll lay out below.
Let's assume that we have two switches that are in the following states:
Switch( name == "switcha", status == "Closed")
Switch( name == "switchb", status == "Closed")
We pass these switches as-is into our rules.
When we're operating in Cloud mode, rules are executed during an instant in time rather than over time (which would be Stream mode.) Cloud mode is the default mode and the mode that the majority of applications leverage. Since you make no mention of event streams, I'm going to assume you're running in this mode. (If you have no idea what I'm talking about, you're also likely to be running in Cloud mode; Stream mode is a relatively new addition.) I'm also going to assume a stateful session.
When we call fireAllRules, Drools will look at the rule inputs and figure out which rules have conditions which match those conditions. It will take that subset of rules, figure out their ordering based on salience and natural order, and then execute them.
As it executes those rules, you can modify the rule inputs in several ways.
Call insert. This adds a new fact into working memory.
Call modify. This changes the existing fact data.
Call update. This also changes the existing fact data.
Change the data on the object directly, eg via a getter or a setter.
Depending on how you change the data, this may or may not change how your rules are evaluated.
If you change the data directly, for example via a getter or a setter, this does not cause any re-evaluation of the rules. Any changes are functionally "invisible" to the drools engine. The same rules that were initially identified as being matches are still fired, even if the condition is no longer true because you updated the data in a way that did not cause Drools to re-evaluate these conditions.
If you call update, Drools will re-evaluate the entire rule scope. This is functionally equivalent to changing the data and then refiring the rules again, from the top. Drools will look at all of the rules using the new data in working memory, and redo the process of collecting matches, ordering them, and firing them. It is extremely easy to get into a "looping" situation using update calls.
If you call insert you are adding a new piece of data to working memory. Drools will do a partial re-evaluation of the rules to figure out if there are any new rules which are eligible to fire, or if the previous matches are now invalidated. It will not re-fire any rules which previously matched and were fired. Similarly, if you call modify, you change the existing rule input object properties in some way and Drools will partially re-evaluate based on those changed conditions.
(This is simplified. You can learn more about the nuances by reading the source code or the documentation.)
Since you only show one partial rule, and only say that it fires even "when closing the switch again" though without explaining how the switch was closed, I can come up with several possible ways of triggering this condition based on the previous explanation of how you can change data with (or without) re-evaluating rule conditions.
For example, if you change the switch state by calling a setStatus("Closed") method, rather than by using modify, then the rule will not be aware of the new state.
rule "change switch state invisibly"
when
// some conditions
$b: Switch( name == "switchb", status == "Open" )
then
$b.setStatus("Closed");
end
rule "Electrical Circuit Status"
Switch( name == "switcha", status == "Open" ) // let's assume this is true
Switch( name == "switchb", status == "Open" ) // Also still true!
then
// show alert
end
Since you change the state using setStatus instead of modify, Drools didn't re-evaluate subsequent rule matches and kept the previous matches. Therefore the condition remained true.
To fix, you'd either use modify or (less recommended) update working memory after your change (with the understanding that all rules would be re-evaluated.)
modify ($b) {
setStatus("Closed")
}
In Unreal GameplayAbilitySystem, e.g. Cancel Abilities With Tag is documented with
Cancels any already-executing Ability [..]
and the source code says (in GameplayAbility.h)
Abilities with these tags are cancelled when this ability is executed
To know at design time, which abilities will be affected when setting those tags, it is required to be sure about:
When a GameplayAbility is considered as executed and when as executing?
According to the documentation linked above, the GA is executed with CallActivateAbility(). However, activation can be interrupted, if cooldown/costs conditions are not fulfilled (e.g. "not enough mana") in CommitAbility().
CommitAbility() checks if the ability can be activated via CommitCheck() (cooldown/costs) and only if this succeeds, CommitExecute() is called (which applies cooldown and costs).
Before CommitAbility(), PreActivate() is called, which
1) sets (for instanced GameplayAbilities):
// ...
bIsActive = true;
bIsBlockingOtherAbilities = true;
bIsCancelable = true;
// ...
2) and blocks/cancels other GameplayAbilities with given tags using UAbilitySystemComponent::ApplyAbilityBlockAndCancelTags
Detailed questions which might help to answer the question above:
Is executing a GameplayAbility the same like activating a GameplayAbility or have these terms different meanings? (both terms are used in documentation and function names/variables)
Is a GameplayAbility always considered as executing as soon as PreActivate() is called? (since that function blocks/cancels other abilities via ApplyAbilityBlockAndCancelTags and therefore - according to the second quote above - is considered as executing)
This would imply, that a GameplayAbility is considered as executing
independently from the outcome of CommitAbility()?
as long as UGameplayAbility::ActivateAbility() is executing?
How is a GameplayAbility detected as executing?
Is it enough to check for UGameplayAbility::bIsActive == true (for instanced GameplayAbilities)?
Or are executing abilities registered somewhere in UGameplayAbilitySystem?
...
Hypothesis
The terms activate/execute a GameplayAbility (GA) and active/executing GameplayAbility are used when the abilities influence each other with GameplayTags. So when designing, these terms are important for understanding the GameplayAbility interaction via tags. As a consequence, an:
activated/executed GA may block/cancel other GAs (via adding tags)
deactivated GA may unblock other GAs (via removing tags)
active/executing GA must be able to receive a block/cancel via tag changes, when another GA is executed
Conclusion
To make best usage of tags for controlling the interaction between GameplayAbilities, keep the following in mind: A GameplayAbility is
activated/executed when CallActivateAbility() is called (in blueprint, the Event ActivateAbility and Event ActivateAbilityFromEvent are triggered by that function via ActivateAbility()).
deactivated when EndAbility() is called (which is also called by CancelAbility()).
active/executing between the calls of UAbilitySystemComponent::TryActivateAbility() until EndAbility().
In case that EndAbility() is not called, the GA is executing for the lifetime of ActivateAbility() (again, in blueprints this is almost similar to the lifetime of the implemented Event ActivateAbility and Event ActivateAbilityFromEvent).
Explanation
When a GA is considered activated/executed and deactivated (1, 2)
UAbilitySystemComponent::ApplyAbilityBlockAndCancelTags() triggers GAs to be cancelled or blocked/unblocked. Therefore calls to it define the moment of activate/execute and deactivate.
Block/cancel are called by PreActivate() which is called by CallActivateAbility()
Unblock is called by EndAbility() (which is also called by CancelAbility())
When a GA is considered active/executing (3)
When it can be blocked
A GA can be blocked only during its activation. CanActivateAbility() checks (via DoesAbilitySatisfyTagRequirements()) the blocked tag list of the GameplayAbilitySystemComponent (ASC) (UAbilitySystemComponent::BlockedAbilityTags). If one of the tags is present there, the ability activation is aborted.
and when it can be cancelled (unregarded the fact if the GA allows it)
A GA can be cancelled by other GAs via tags as long as it is registered in the GameplayAbilitySystemComponent (ASC) in UAbilitySystemComponent::ActivatableAbilities and as long as that stored GA spec returns FGameplayAbilitySpec::IsActive() = true.
It gets added to that container via UAbilitySystemComponent::GiveAbility() and removed via UAbilitySystemComponent::ClearAbility()
FGameplayAbilitySpec::IsActive() will return true, as long as FGameplayAbilitySpec::ActiveCount > 0. This variable will be incremented upon GA activation (in UAbilitySystemComponent::InternalTryActivateAbility()) and decremented upon GA deactivation (in UAbilitySystemComponent::NotifyAbilityEnded).
UASC::InternalTryActivateAbility() is called in UASC::TryActivateAbility() and UASC::NotifyAbilityEnded() is called in EndAbility(). These two conditions are the reason that I considered a GA only as active/executing between those calls instead of between UASC::GiveAbility() and UASC::ClearAbility().
How those tags are triggered
When a GA is activated/deactivated, it triggers functions in the GameplayAbilitySystemComponent (ASC):
For un-/blocking
UAbilitySystemComponent::ApplyAbilityBlockAndCancelTags calls ...
UAbilitySystemComponent::BlockAbilitiesWithTags() respectively UAbilitySystemComponent::UnBlockAbilitiesWithTags(), which (finally) call for each of the tags in its list UAbilitySystemComponent::BlockedAbilityTags ...
FGameplayTagCountContainer::UpdateTagMap_Internal(), which adds respectively removes the tag
For cancelling
UAbilitySystemComponent::CancelAbilities() which compares the tags provided by the cancelling GA with the tags of all activateable abilities stored in the Ability System Component (in UAbilitySystemComponent::ActivatableAbilities()), which are currently active.
If there is a match, all of those GA instances are cancelled.
What about CommitExecute()
That function is independent from interacting with other GAs via tags, so the Execute part of the name can be misleading.
CommitExecute() is called only if the costs of the GA can be afforded and if the GA is not on cooldown (all of that happens in CommitAbility()). But blocking/cancelling other GAs already happened before and unblocking GAs also happens independently from that function.
So what about CommitAbility()
For an executing GA, it doesn't matter, if this is being called.
If CommitAbility() fails, the GA might be deactivated immediately after being activated, depending on the implementation of the GA. So it can have an influence on the execution duration, which however is unimportant for the design process of the GAs interaction via tags.
What about SetShouldBlockOtherAbilities()
This public function can be called to un-/block other GAs via tags from an arbitrary place in C++/blueprints.
E.g. it could be called several times during the lifetime of ActivateAbility() to un-/block other GAs. Furthermore, it is not able to cancel other GAs. It is not clear what are the best practices for using or avoiding this function. It seems to lower the transparency of GA interaction via tags.
(if no parent namespace is present, all functions are members of UGameplayAbility)
Other ways to block/unblock GAs (e.g. via inputID) or cancelling GAs (e.g. via UAbilitySystemComponent::CancelAllAbilities()) are not considered. This is about GA interaction via tags. Also triggering GAs via tags (or GameplayEvents) is another topic.
It would be nice if a designer of the Unreal GAS could clarify things, correct incomplete conclusions or leave some words about best practices.
I am working with a library (ScalaJS and react specifically) where I have an interesting situation that I assume is pretty routine for an experienced reactive-programmer. I have a Component with State and a callback shouldComponentUpdate(State). The basic idea here is that certainly if the callback is triggered but the State has not changed from the last render, returnfalse. Otherwise, perhaps return true if the State change matters.
I am using a library monix but it seems identical to other reactive libraries so I would imagine this is a fairly context-independent question.
I would like to do something like: have some state that reflects the deltas of State since the last render. On each render, clear the buffer. Or, have a renderedState subject that reflects all rendered states as a sequence, a receivedState subject that reflects all received State updates, and a needsUpdate subject that reflects whether the latest receivedState matches the latest renderedState. I am having trouble actually executing these ideas, though. Here is where I am stuck at:
Here is what I've done for other callbacks:
lazy val channel_componentWillUpdate = channel_create[ComponentWillUpdate[Props, State, ResponsiveLayoutContainerBackend, TopNode]]
def componentWillUpdate(cwupd: ComponentWillUpdate[Props, State, ResponsiveLayoutContainerBackend, TopNode]) =
Callback {
channel_componentWillUpdate.onNext(cwupd)
}
So when then componentWillUpdate callback is triggered, the handler fires onNext on the channel (subject).
The shouldComponentUpdate is different though. It returns a value, so it needs to be structured differently. I am having trouble thinking of the right adjustment.
To summarize a bit:
react has callbacks at different stages of the view lifecycle, like componentDidMount, componentDidUpdate, etc.
I am handling all but one stage the same way - the shape of the callback is State -> Callback<Void> so alls I have to do is use a Subject for each type of lifecycle event and submit its onNext when the callback is triggered.
But one type of event has shape either State -> Boolean or State -> Callback<Boolean>.
I feel like I should be able to model this with a subject representing the delta between the last state rendered/received.
However, I don't know how this fits into the reactive style.
I need to add an Action to a Schedule object that is being created through the API. There are documented interfaces to set almost all the options except the Action. How are Actions attached to these Objects?
When I attempt to programmatically add a new event, read from a separate configuration file, to a Schedule object I get errors stating that the Schedule has already been initialized and that I must construct a new object and add its configuration manually. I can do most of that using the available Schedule API. I can set up everything about the Schedule except the Action code.
The Schedule is used in a Process Model. Looking at the model in the Java editor, I see the code I'm trying to replicate via the API in a function that looks like this:
#Override
#AnyLogicInternalCodegenAPI
public void executeActionOf( EventTimeout _e ) {
if ( _e == _fuelDeliverySchedule_Action_xjal ) {
Schedule<Integer> self = this.fuelDeliverySchedule;
Integer value = fuelDeliverySchedule.getValue();
logger.info("{} received {} pounds of fuel", this.getName(), this.fuelDeliverySchedule.getValue());
this.fuelAvailablePounds += fuelDeliverySchedule.getValue();
;
_fuelDeliverySchedule_Action_xjal.restartTo( fuelDeliverySchedule.getTimeOfNextValue() );
return;
}
super.executeActionOf( _e );
}
Maybe I can use something like this to create my own action function, but I'm not sure how to make the Scheduled event use it.
Thanks,
Thom
[Edited (expanded/rewrote) 03.11.2014 after more user detail on the context.]
You clarified the context with
When I attempt to programatically add "a thing that happens", read
from a separate configuration file, to a Schedule object I get errors
stating that the Schedule has already been initialized and that I must
construct a new object and add its configuration manually. I can do
most of that using the available Schedule API. I can set up everything
about the Schedule except the Action code.
(You might want to edit that into the question... In general, it's always good to explain the context for why you're trying to do the thing.)
I think I understand now. I presume that your config file contains scheduling details and, when you say you were trying to "add a thing that happens" (which errored), you meant that you were trying to change the scheduling 'pattern' in the Schedule. So your problem is that, since you couldn't adjust a pre-existing schedule, you had to instantiate (create) your own programmatically, but the Schedule API doesn't allow you to set the action code (as seen on the GUI schedule element).
This is a fairly involved solution so bear with me. I give a brief 'tl;dr'
summary before diving into the detail.
Summary
You can't programmatically code an AnyLogic action (for any element) because that would amount to
dynamically creating a Java class. Solving your problem requires recognising
that the schedule GUI element creates both a Schedule instance and a
timeout event (EventTimeout) instance to trigger the action. You can therefore create these two elements explicitly yourself (the former dynamically). The trick is to reset the timeout event when you replace the Schedule instance (to trigger at the next 'flip' point of the new Schedule).
[Actually, from your wording, I suspect that the action is always the same but, for generality, I show how you could handle it if your config file details might want to change the nature of the action as well as those of the scheduling pattern.]
Detail
The issue is that the GUI element (confusingly) isn't just a Schedule instance
in terms of the code it generates. There is one (with the same name as that of
the GUI element), which just contains the schedule 'pattern' and, as in the API,
has methods to determine when the next on/off period (for an on/off schedule) occurs. (So
it is kind of fancy calendar functionality.) But AnyLogic also generates a
timeout event to actually perform the action; if you look further in the code
generated, you'll see stuff similar to the below (assuming your GUI schedule is called
fuelSchedule, with Java comments added by
me):
// Definition of the timeout event
#AnyLogicInternalCodegenAPI
public EventTimeout _fuelSchedule_Action_xjal = new EventTimeout(this);
// First occurrence time of the event as the next schedule on/off change
// time
#Override
#AnyLogicInternalCodegenAPI
public double getFirstOccurrenceTime( EventTimeout _e ) {
if ( _e == _fuelSchedule_Action_xjal ) return fuelSchedule.getTimeOfValue() == time() ? time() : fuelSchedule.getTimeOfNextValue();
return super.getFirstOccurrenceTime( _e );
}
// After your user action code, the event is rescheduled for the next
// schedule on/off change time
_fuelSchedule_Action_xjal.restartTo( fuelSchedule.getTimeOfNextValue() );
i.e., this creates an event which triggers each time the schedule 'flips', and performs the action specified in the GUI schedule element.
So there is no action to change on the Schedule instance; it's actually related to the EventTimeout instance. However, you can't programmatically change it there (or create a new one dynamically) for the same reason that you can't change the action of any AnyLogic element:
this would effectively be programmatically
creating a Java class definition, which isn't possible without very specialised
Java code. (You can create Java source code in a string and
dynamically run a Java compiler on it to generate a class. However, this is very
'advanced' Java, has lots of potential pitfalls, and I would definitely not
recommend going that route. You would also have to be creating source for a user subclass
of EventTimeout, since you don't know the correct source code for AnyLogic's proprietary EventTimeout class, and this might change per release in any case.)
But you shouldn't need to: there should be a strict set of possible actions that your config file can contain. (They can't be arbitrary Java code snippets, since they have to 'fit in' with the simulation.) So you can do what you want by programmatically creating the Schedule but with a GUI-created timeout event that you adjust accordingly(assuming an off/on schedule here and that there is
only one schedule active at once; obviously tweak this skeleton to your needs
and I haven't completely tested this in AnyLogic):
1. Have an AnyLogic variable activeAction which specifies the current active
action. (I take this as an int here for simplicity, but it's better to use a
Java enum which is the same as an AnyLogic 7 Option List, and can just be
created in raw Java in AnyLogic 6.)
2. Create a variable in the GUI, say called fuelSchedule, of type Schedule but with initial value null. Create a separate timeout event, say called fuelScheduleTrigger, in User Control mode, with action as:
// Perform the appropriate action (dependent on activeAction)
doAppropriateScheduleAction();
// Set the event to retrigger at the next schedule on/off switch time
fuelScheduleTrigger.restartTo(fuelSchedule.getTimeOfNextValue());
(Being in User Control mode, this event isn't yet triggered to initially fire, which is what we want.)
3. Code a set of functions for each of the different action alternatives; let's say
there are only 2 (fuelAction1 and fuelAction2) here as an example. Code
doAppropriateScheduleAction as:
if (activeAction == 1) {
fuelAction1();
}
else if (activeAction == 2) {
fuelAction2();
}
4. In your code which reads the config file and gets updated schedule info.
(presumably run from a cyclic timeout event or similar), have this replace
fuelSchedule with a new instance with the revised schedule pattern (as you've
been doing), set activeAction appropriately, and then reset the timeout event to
the new fuelSchedule.getTimeOfValue() time:
[set up fuelSchedule and activeAction]
// Reset schedule action to match revised schedule
fuelScheduleTrigger.restartTo(fuelSchedule.getTimeOfNextValue());
I think this works OK in the edge case when the new Schedule had its next 'flip' at the time
you set it up. (If you restart an event to the current time, I think it schedules an event OK at the current time which will occur next if there are no other events also scheduled for the current time; actually, it will definitely occur next if you are using a LIFO simultaneous-time-scheduling regime---see my blog post.)
Alternative & AnyLogic Enhancement
An alternative is to create a 'full' schedule in the GUI with action as earlier. Your config file reading code can replace the underlying Schedule instance and then reset the internal AnyLogic-generated timeout event. However, this is less preferable because you are relying on an internally-named AnyLogic event (which might also change in future AnyLogic releases, breaking your code).
AnyLogic could help this situation by adding a method to the Schedule API that gets the related timeout event; e.g., getActionTriggeringEventTimeout(). Then you would be able to 'properly' restart it and the Schedule API would make much clearer that the Schedule was always associated with an EventTimeout that did the triggering for the action.
Of course, AnyLogic could also go further by changing Schedule to allow scheduling details to be changed dynamically (and internally handling the required updates to the timeout event if it continued to be designed like that), but that's a lot more work and there may be deeper technical reasons why they wanted the schedule pattern to be fixed once the Schedule is initialised.
Any AnyLogic support staff reading?
I have two input fields which i would like to sync with each other.
Unfortunately, when I add a ChangeListener to each of the TextFields they will trigger each other,
and so create an andless loop.
Ofcourse I could unregister the Listeners, on every change and them put them back,
but is there any Java native approach?
Maybe something with bindings?
From general reasoning (i.e. not knowing swt or java): you can add a boolean flag (probably your class member) m_enteredChangeListener, temporary setting it to true in one of your handlers (not both), making the same handler do nothing if it's reentered recursively.