Unexpected behavior SelectOutput block in AnyLogic - anylogic

In a model I use a selectoutput block using a condition, based on the agent's p_Dx_EGFR_SOC_AH parameter, which is of type Option list (options: Mutated, NotMutated, UnknownStatus). If agent.p_Dx_EGFR_SOC_AH == Mutated evaluates to true, then the exit via the true port, otherwise they exit through the false port. To check whether it works correctly, I included a traceln(agent.p_Dx_EGFR_SOC_AH); in the On exit (True) field of that selectoutput block.
It turns out it's not working as expected. The traceline shows that agents with either of the three options of the parameter exit through the True port:
This is also true for the False port; agents with either of the three options exit through that port. Am I doing something wrong here, or is this a known bug in AnyLogic?

The problem here, is that the order in which things are calculated is in reverse... so let's imagine the following model and the condition to exit true is agent.parameter==0 and the default value of the parameter is 0
the order in which things happens is
the agent is on at the exit port of the source block
the agent calculates the condition on the selectoutput block
the agent moves out of the source block and makes the calculations on the "on exit" action
that means that if you change the value of the parameter on the on exit action of the source block agent.parameter=1, the agent will still exit on the true exit of the selectoutput becacuse the condition was already calculated
if you change the value of the parameter on the on at exit action, the agent will exit through the false exit of the selectoutput block
It's a bit weird, but that's the way things are done
Sometimes you don't have the "on at exit" action, in which case you might need in between an auxiliary delay of 1 milisecond in order to have the order you want.

Related

Anylogic: StopDelay() is not working due to which agent is not able to leave the Delay block

StopDelay() is not working due to which agent is not able to leave the Delay3 block.
of course your stopDelay won't work because no agent ever reaches delay4
delay3 REQUIRES a call for stopDelay, but there's nothing doing that since the only time stopDelay is called, is further in the flow.
What you need to do instead is on the on enter action of the delay3:
if(delay4.size()==0){
delay3.stopDelay(agent);
}
and on the on exit of the delay4 you do:
if(delay3.size()>0){
delay3.stopDelay(delay3.get(0));
}

Anylogic - Assembler should stop working for 2 hours after 10 assemblies done

The "Assembler" should stop working for 2 hours after 10 assemblies are done.
How can I achieve that?
There are so many ways to do this depending on what it means to stop working and what the implications are for the incoming parts.. but here's one option
create a resourcePool called Machine, this will be used along with the technicians:
on the "on exit" action of the assembler do this (I use 9 instead of 10 because the out.count() doesn't count until the agent is completely out, so when it counts 9, it means that you have produced 10)
if(self.out.count()==9){
machine.set_capacity(0);
create_MyDynamicEvent(2, HOUR);
}
In your dynamice event (that you have to create) you will add the following code:
machine.set_capacity(1);
A second option is to have a variable countAssembler count the number of items produced... then
on exit you write countAssembler++;
on enter delay you write the following:
if(countAssembler==10){
self.suspend(agent);
create_MyDynamicEvent(2, HOUR,agent);
}
on the dynamic event you write:
assembler.resume(agent);
Don't forget to add the parameter needed in the dynamic event:
Create a variable called countAssembler of type int. Increment this as agents pass through the assembler. Also create a variable called assemblerStopTime. You also record the assembler stop time with assemblerStopTime=time()
Place a selectOutputOut block before the and let them in if countAssembler value is less than 10. Otherwise send to a Wait block.
Now, to maintain the FIFO rule, in the first selectOutputOut condition, you need to check also if there is any agent in the wait block and if the current time - assemblerStopTime is greater than 2. If there is, you free it and send to the assembler with wait.free(0) function. And send the current agent to wait. You also need to reset the countAssembler to zero.

Why do not agents go out from the queue?

I have a queue,followed by selectoutput. the problem is that the agent does not go out from the queue.In this case the agent should choose the third exit of the selectoutput, so it is not possible (i presume) that the agent does not go out because the following block is full.What could be the reason? Thanks
the reason is that the condition that you think is true, is actually false, because anylogic calculates first the condition in the select output block, and then it runs the code on the "on exit" action of the queue7 block...
So my guess here, is that you are doing something on the on exit action, that changes the result for the condition.. but it's already too late..
use the "on at exit" action or sometimes you need to put a dummy delay of 1 milisecond or so between your last block before the selectoutput and the selectoutput to ensure your condition is met correctly
This is the order in which things happen:
on at exit queue
check condition
on exit queue
on enter select output

Product ID in agent-ANYLOGIC

I have created an agent ("Handsfree") in the agent I introduced parameter "WIRE". How do i make that parameter vary as simulation goes on so that it should automatically be set to either true or false so that i could assign the delay a specific time according to the parameter "WIRE".
When does WIRE switch between true and false values? Is it based on time? If so, you can write a simple function to switch the initial value from true to false (or vice-versa). That function could also set the delay time in another parameter, "pDelayTime". Then, you'd call that function with an event at specified or random times (whatever is needed). The delay time in your block would need to be set to "pDelayTime".

Talend ETL - running child job in tLoop

I am trying to run a child job in tLoop. The child job connects to salesforce and downloads "Account" object to local SQL Server table. There are problems with connection to Salesforce, it takes few attempts to connect. Hence, I put the connection stuff in child job and now trying to call the child job in a loop. Below is the image of my parent job.
As you can see in image the tRunJob_1 has error because of Salesforce connection problem in child job. This is correct behaviour.
The setRetryConnect that is connected to OnComponentError has this code: context.retryConnect = true;
The setRetryConnect that is connected to OnComponentOk has this code: context.retryConnect = false;
So, I am tripping this context variable depending on whether child job succeeds or fails.
My tLoop looks as below:
I want the tLoop to run as many times till the condition remains true. That is till the time it continues to error out. However, it just iterates once and then stops. Could anyone please let me know what correction need to be done here to make the tLoop work?
I couldn't re-pro your issue with SalesForce but by looking at your job what I feel is that when you say - "it just iterates once and then stops" is the expected behavior.
As per your job flow after the tRunJob you are using OnComponentOk/OnComponentError trigger which would process and stop the job run as it would have completed the job execution. What it would have ideal was to keep everything in a subjob post tLoop so that it will iterate till the condition is met.
Sample job for explanation -
Here used tSetGlobalVar to define a global variable (in place of your context variable). Then use the globalMap variable as ((Boolean)globalMap.get("tLoop")) in your "Condition" for the tLoop.
And then finally run some code in the tJava component that does something and conditionally sets the global variable to false to mark the ending of loop.
tRunJob provides an Return Code ((Integer)globalMap.get("tRunJob_1_CHILD_RETURN_CODE"))
If you're running your child Job a number of times and want your Job to exit with non-Zero if one of these iterations fails, then after each iteration, you should test this return code and store it in your own globalMap Object if it is non-zero
int returnCode = ((Integer)globalMap.get("tRunJob_1_CHILD_RETURN_CODE"));
if (returnCode > 0) {
globalMap.put("tLoop", false);
}
else {
System.out.println(returnCode);
};
Found the answer myself, posting it here so that it may help others. It appears like OnComponentError breaks the tLoop. Disabled the OnComponentError flow and un-checked the 'Die on Child Error' checkbox in tRunJob.
The tLoop remains as it is. No changes here.
The retryConnect will use the below code. It uses CHILD_RETURN_CODE to check whether the child job threw error. In case of success, its value is 0. I am tripping the variable when the child job succeeds, so the loop will stop. As you can see, the tLoop shows 2 iterations, it is working as expected now. Thanks.