How to set TimeMeasureStart dynamically? - anylogic

I have a model of a supply chain in which my agents "Product" pass through blocks in some agents (i.e. "Vendor", "Factory", "Wholesaler", and "Retailer") and I have a flowchart block in which the said agents in the supply chain use it. I would like to measure the time my agent "Product" spent, which its TimeMeasureStart is in for example its "Vendor" page and its following TimeMeasureEnd is in the said flowchart block like this. Now I have difficulty defining TimeMeasureStart in the TimeMeasureEnd block in the flowchart block.
I tried to use getRootAgent() but this way I couldn't access the timeMeasureStart block of the root agent so I couldn't try this.
Also tried to define a variable in the flowchart block page like this (and I know this way is wrong but I have no idea how to define a variable to suit TimeMeasureStart)
and then use it to define the corresponding TimeMeasureBlock the "Product" had passed: timeMeasureEnd Properties
but it gave me these 2 errors:
Type mismatch: cannot convert from TimeMeasureStart[] to TimeMeasureStart.
Variable must provide either dimension expressions or an array initializer.
Also tried set_startObjects but I didn't understand how to work with it and couldn't find the documentation in AnyLogic Help.
I really would appreciate any help.
(Also so sorry if the images are blurry, I don't know why their quality gets like this when I upload them.)

Either use
((Main)getRootAgent()).timeMeasureStart()
Or simply use
main.timeMeasureStart
Both take you back to Main. The former uses type casting, the latter is a direct link created by AnyLogic (assumes your timemeasureStart is in an agent embedded in Main)

Related

Accessibility of main from agent's statechart

May I know if main is accessible to all elements in the model?
The reason I ask is that I have created a simple M/M/n model with one resource type created through ResourcePool. The behaviour of the resource type is implemented using a statechart. I write a simple code in the action of a transition in the statechart, i.e.
if (agent_variable < main.my_parameter) { /* do something */ }
The code does not compile and give an error message "main cannot be resolved to a variable". I cannot figure out why the statechart cannot recognise main.
Thanks
Welcome to SOF, Stephan.
First, always use code-complete (Ctrl+space). You will then see what is and what is not possible to access from where you are. In your case, main would not even be an option :-)
Now, your model root (typically that is main) is always accessible via getModelRootAgent() but you will need to cast it to your Main class, i.e. ((Main)getModelRootAgent())
Otherwise, Main is accessible to all agents that are somehow embedded into Main. This is classic OOP principles. Your Resource agents are not actually an embedded population so no direct access to Main. (You can make that happen in the ResourcePool properties, though)

How to change parameter in variation experiment that are not in main?

I would like to set up an parameter variation experiment in AL. I have an agent population and a single agent in the main agent. All parameters are not stored in main but in the embedded agents. The problem I face now is that I can`t see these parameters in the experiment setup window. Is it required that all parameters are defined in main?
Thank you!
In such a case, you use "Parameter propagation" as explained in the AnyLogic help.

Anylogic: Declare parameter of type ArrayList

I'm building a class (sorry - Agent) that will work with a set of Tank objects (Fluid Library) - doing things like monitoring individual levels or total level of all tanks, reporting on levels and initiating actions based on levels - things of that nature. For argument's sake let's call it a "TankMonitor" agent.
Ideally I'd like to be able to define a Parameter in my "TankMonitor" agent that allows me to define the tanks of interest when I place a TankMonitor in main. I have tried to define the type of the parameter as Other - ArrayList<Tank> however I don't know how to set up the next step to allow me to populate the ArrayList of Tanks when I put an instance of this agent in main. My preference would be to have a list type control to populate the ArrayList - much like the way the AnyLogic Seize block allows you to specify multiple resource pools to choose from.
Has anyone attempted this before and been successful?
This is possible as follows:
Change the type to "Other" and then 'Tank[]' , i.e. an Array of Tanks
Change the control type to "one-dimensional array"
Example below. Now you have the same UI to pre-define tanks at design time for your agent instance.
In addition to Benjamin's perfect answer, I'd just add the manual workaround, which is not needed here but can be useful when the parameter in question has a more complicated structure than covered by the pre-made controls, say a list of lists, a map, or similar.
In such a case, the Control Type is still Text, and populating it in an instance happens by pointing it to a new object of the parameter's type. E.g. for an ArrayList<Tank> parameter, you might instantiate a new ArrayList object, which you fill with a list of objects like so:
new ArrayList<Tank>(Arrays.asList(tankA, tankB))
In the Java code, whatever is written into that text box will end up on the right side of a parameter assignment statement in the embedded Agent instance's auto-generated parameter setup function. Therefore, multi-statement code won't work in this spot. Instead, if the process of building the parameter value doesn't fit neatly into a single expression, you can hide the code in a function which returns the desired object, and call that from the parameter's text box.

How to select output in Anylogic by agent parameter?

So, I'm pretty new with Anylogic, but have done a lot of tutorials and I have programming experience in Java. For my thesis I'm modelling a vehicle flow as a process. In the source block, I create custom agents (vehicles) with some parameters from the database. This works fine. Then I want to assign an electric parameter with randomTrue(0.5). For this, I call a setupTaxi-function, where electric ist set. The parameter for the randomTrue-function should be changeable, so I set it as an extra paramter anteilEtaxis (0.5).
After that, I want the vehicles to do different things depending on the value of electric using SelectOutput. I selected the Condition and test on agent.electric.
I basically did the exact same thing as described in the Anylogic help. And yet the framework always chooses the true Output port, no matter if the parameter ist set to true or false.
See the image for setup and parameters. I tested this via console (the first line is a println-call in source, the second a println-call in selectOutput.). Plus you can see that the parameter is set to different values, because the 3D visualisation model depends on it:
enter image description here
Also, I tried a few different combinations of setting the parameters, reading them etc... The only thing that will work is putting randomTrue(0.5) directly in the Condition box. This is not what I want though. So if you have an idea, what is wrong, please tell me.
This is a typical beginners problem.
I will assume you are calling the setupTaxi-function in your source in the "on exit" action... If you are doing that, then it's too late and the agent already made its decision on where it will go after the select output block.
You have to call your setupTaxi-function in 2 possible places:
1) In your source on the "on at exit" action
2) In your vehicle agent on the "on startup" action
Or even.. just make electric variable have a default value of randomTrue(main.anteilEtaxis)... that will also work.

Windows Workflow - IfElse branch

I am trying to use Windows Workflow and have a model that looks similar to the image in the link below:
After each of the Send Activities (GetSomthing, GetSomthingElse, GetSomeMoreStuff) the same custom activity is being called (LogSomthingBadHappened).
While it might not look so bad in this picture in my real model the custom activity is a SequenceActivty, has quite a few nodes, and when its repeated 3 times starts to make the workflow look very ugly.
I would like to do something like this:
Can the IfElse branches be merged like this?
Should I be using a State Machine work flow instead (haven't figured these out yet)?
Use a FaultHandler on the workflow and throw a specific exception type that the handler will catch. Not the most graceful, but I think it should work.
In sequential workflows all steps must appear in a specific order, and the execution path is regulated exclusively by control structures (IF, WHILE).Altering the execution path in the way you describe would be like using a GOTO statement in imperative code, which we know leads to unnecessary complexity.
If the activities contained in the SequenceActivity that you need to execute at different stages of your workflow are exacty the same, you could embed them in a custom activity. This way it is easier to manage them since they are contained in a single logical unit.In imperative code, this would be like refactoring out a portion of duplicated code into a method, which is then invoked multiple places.
Another alternative that might work is to put your LogSomthingBadHappened activity into a custom workflow and include that several time. Several things to watch out for: Subworkflow are executed asynchronously, if the LogSomthingBadHappened activity needs state information from the main workflow, copying it to the sub workflow might be hard.
I have not tried this, so it might not even work.
I think the answer by gbanfill points to the right direction.
To generalize, I define the problem as:
Is there a way to define a group of activities that will be executed in several places of a workflow?
Further requirements are:
The group of activities should be defined in XAML only ie no code.
Type of input to this group will, of course, be fixed but actual values should depend on call (like calling a function).
Maybe the way to do it is define sub-workflows and build a custom activity that would instantiate the sub-workflow and wait for it to complete before continuing.
This custom activity should have at least two parameters: the sub-workflow id and input parameters.