I inserted a condition in the event window , this conditions refers to a variable in my main agent. I dont't understand why the condition is not evaluated by the event . I searched on the help and it suggest to use the onChange function , but i can't understand where and how to use it.
Thanks
The onChange is used to make sure the condition is evaluated when it needs to in case AnyLogic missed it, since AnyLogic does not evaluate the conditions every moment in time, instead, it just evaluates them at important time steps.
So, where to put onChange() depends on what your condition is. For example, if you condition is having a queue length of say 10, then I would add the onChange() function on the "On Enter" and "On Exit" of the queue, so that each time an agent enters or leaves the queue, the condition is evaluated.
So again, where to use onChange depends on what your condition is. If this doesn't help, feel free to provide more details on what your condition is.
Related
I'm wondering whether it is possible to change a block parameter in Simulink (or the value of one saved as a variable) using a different block to enable conditional execution. What I would like to do is have a certain block parameter (in this case, Counter) run during the simulation with an initial value, and have it change to a different value if a certain condition is satisfied.
Ultimately, what I would like to get out of this is to get a Counter block to stop running upon the satisfaction of that condition.
I'm pretty new to Simulink, but I'll detail some of the stuff I've tried so far:
Dashboard switches (Slider, Knob etc.) - I know they're used to
change tunable parameters of blocks, but they cannot be linked to
other blocked and can be only be controlled manually.
Matlab Function block - didn't seem to work, I'm obviously missing something.
Is it maybe possible to disable a certain block/link when that condition is met? That would be a straight forward approach, but I'm not sure it can be implemented in Simulink. Any help would be appreciated!
So to meet your ultimate goal have you considered to place your counter in an enabled subsytem?
Whenever the requirements are met to stop the counter you simply disable the subsystem and the counter will stop.
On the output port of that enabled subsystem you will have the options to preserve the last value or reset it to certain one.
I think the correct description for what I'm trying to do is be able to pass an expression or function/handler into another handler as a parameter/argument. Some code to be evaluated inside the receiving handler. Similar to Javascript callbacks, I think.
For example, something like this:
on waitFor(theConditionExpression)
timeout_start(5) -- start a 5 second timer
repeat until (theConditionExpression or timeout_isExpired())
delay 0.1
end repeat
return theConditionExpression
end waitFor
theConditionExpression should be some expression or function that evaluates to a boolean result.
not really relevant to the question, but just FYI, timeout_start(…) and timeout_isExpired() are two simple handlers I've written that do exactly what they say. (…start() doesn't return anything, …isExpired() returns a boolean).
Of course, typically if I pass in some boolean expression, it will evaluate that expression once, at the time I pass it in. But I want it to evaluate it every time it's referenced in the code inside the handler.
Some languages (not sure about AS) have some kind of eval() function that you can pass it some code as a string and it will execute that string as code. Theoretically that could solve this, but: (a) I don't know if AS has anything like that, but even if it does, (b) it's not desired for various reasons (performance, injection risks, etc.)
So I'm thinking something more like eg. JavaScript's ability to pass in a function (named or anonymous) as function parameter/argument that can be re-evaluated every iteration in a loop, etc. (eg. like the compareFn argument in JS's Array.sort(compareFn)).
Can AS do anything like this, and if so how?
Thanks!
I'm going to suggest (pro forma) that an AppleScript application with an on idle handler is generally a better solution for wait conditions than a repeat/delay loop. It's more efficient for the system, and doesn't freeze up the script. But that would involve reconceptualizing your script, and I'm not certain it would work in this case, given the way you formed the problem.
There's an old but good site called AppleScript Power Handlers that shows a bunch of nifty-neato tricks for sophisticated use of AppleScript handlers: passing handlers as values or parameters; creating Script Objects within handlers; making closures and constructors. I'm pretty sure the answer to your request is in there. aLikely you'll want to set up a bunch of handlers that serve as condition expressions, then pass them as parameters to the evaluating handler. Or maybe you'll want to set up a script object containing the condition handlers and call it as needed?
At any rate, see what you can do with it, and ask more specific questions if you run into problems.
I want to use SelectOutput5 block in order to differentiate same agents according to machines which they have been assigned. As you can see the images, one of the example of my SelectOutput5 block's condition is;
agent.st2Tezgah == "M117";
However even though st2Tezgah parameter has M117 value in it, it does not trigger and it goes false section.
I check the parameter with traceln(agent.st2Tezgah) as you can see the image, the value is true.
Why SelectOutput5 does not trigger properly?
Flowchart
Code
Traceln
st2Tezgah parameter
DB
Result
Two things:
Always compare strings using .equals("myString"), not ==.
Make sure you do not set the st2Tezgah variable "just before" the SelectOutput5. Try having a delay (with 0 duration) before it and see if it works. If so, you need to learn about the difference of "on exit" and "on at exit" (subtle but important here)
I have a source and a variable. in the "on exit" source section there is "variable=source.count()". The source generates n agents by inject fuction, but the variable has value n-1. why?
thanks for the help.
so I assume you want to count the agents that have been generated on that source.
Using a variable is in the first place redundant since you can use source.count() everywhere in your model instead of the variable, and it will work.
Nevertheless if you insist in using a variable, you need to use the variable in the block AFTER the source since it seems that the count is made internally in anylogic after the "on exit" action.
so for instance if you have a delay block after the source, write variable=source.out.count(); in the "on enter" action of the delay block.
Anylogic: This should be simple but I just cannot find it in the help files..
On creating a new agent instance, we know there are four parameters and what they are, but not in what order they were defined. Lets say parameters are "type_of_car" (String), "number_of_pax" (Integer), "automatic" (boolean), "fuel_capacity" (double). Now when calling: new myagenttype("ford", 5, false, 55) the agent gets created as a ford with 55 pax, manual and 5 liter fuel capacity - which is all wrong. (it seems the definition order of the parameters in the agent definition are in a different order)
How do we include the parameter name (or definition) when we call new agenttype() to avoid this problem, ensuring the right value gets assigned to the right parameter?
The problem originates because of a bug in Anylogic's logic in triggering functions. We have a Split which creates a new agent and assigns the agent properties on the "On exit copy" - event, however what Anylogic does is it creates the agent, forward it to the next logical block (a decision node), then execute the code of the decision - all wrong now for the agent's properties are undefined - and only then executes the "On exit copy" event which assigns the agent's properties. Very frustrating.
This is actually not a bug, this is defined in the simulation experiment properties, in the randomness section, with the "selection mode for simultaneous events" property. The default is LIFO, but if you want the opposite behavior in your case you should use FIFO... I always use LIFO too, and in these cases, sometimes I might use a 1milisecond auxiliary delay between the split and the next block in order to control the order manually... if you do that, you will solver your problem in fact... just use a 0.001 miliseconds delay after your split
Now from your Agent Type problem, the arguments for your class constructor should be written in order, and the only way to know the correct order is by using the autocomplete feature when you write new agenttype()... the autocomplete will tell you the order in which you should write your constructor arguments.