Split the agents equally using SelectOutput5 in AnyLogic - simulation

I am using selectOutput5 in my model.
On the basis of the probability being equal for all the output ports, The number of agents who came out should be equal, but that is not the case.
Please let me know how I can split the agents equally.

You should also understand why this happens: The conditions are computed sequentially, not at the same time.
So it first checks the first condition. Only if that is false will it even bother with the second, and so on.
So you'd need to have larger values from 1 condition to the next, which is not elegant.

if you want them to be split equally you can use the "Exit Number" option and use a counter that will increment everytime, and when it reaches 3, the counter goes back to 1
so the counter starts with 1
Exit Number is equal to counter
then whenever an agent exits, you do
counter++;
if(counter==4) counter=1;

Instead of using probability, I use the condition for selectOutput5.
For example:
If I have 3 racks, I want to split 18 agents equally among them. Then my conditions in selectoutput5 will look like this.
condition 1 : RackStore1.size() <6
condition 2 : Rackstore2.size() <6
condition 3 : Rackstore3.size() <6
condition 4 : false
The agents will split equally among the racks.

Related

Simulating first come first serve agent distribution

I currently have agents of type patient seizing an exam room when it becomes available, then, to mimic a first come first serve system where different healthcare practitioners see the patient, I have utilized a SelectOutputIn and 4 SelectOutputOut blocks corresponding to the 4 different practitioners that can see the patient. Each SelectOutputOut block has the same probability corresponding to their resource type. The problem arises when all practitioners are busy, it seems to send patients only to the Physio path and overload it. Is this because it is physically the last block in the order? How can I make the distribution of patients random even if all practitioners are busy?
[][1
It is correct. If all probabilities are zero, AnyLogic seems to pick the last option. To address your issue, we need to add a condition for when all practitioners are busy. So you will have 3 possible outcomes as follows:
Surgeons.idle() + Fellows.idle() + Residents.idle() + Physios.idle() == 0 ? 0.25 : Surgeons.idle() > 0 ? 0.25 : 0
The difference between the first and second 0.25 is that in the first case, all ports will have a 0.25 probability. Whereas in the second case, 3 of 4, or 2 of 4 or even 1 of 4 will have a 0.25 probability depending on how many resources are available. AnyLogic normalizes the probabilities. So if two ports have 0.25 probability, then it's like saying it's a 50/50 chance.
Finally, if the code seems too long, you can replace the first part by a function to have a cleaner/shorter code.
The function body could be:
return Surgeons.idle() + Fellows.idle() + Residents.idle() + Physios.idle();
Assume you named the function function, you can simplify your code in the probability field as follows:
function() == 0 ? 0.25 : Surgeons.idle() > 0 ? 0.25 : 0

How does the scan operator help to identify indices where a rule holds for 2 observations in a row?

A boolean vector has been created based on some rule and we need to identify the indices where the rule holds for 2 observations in a row. The following code does that
indices:0101001101b
runs:{0 x\x}"f"$;
where 2=runs indices
Could you please help me understand how the scan operator is used in the definition of the runs function? Appreciate your help.
It's using this special shorthand commonly used in calculating exponential moving averages: https://code.kx.com/q/ref/accumulators/#alternative-syntax
So {0 x\x} is equivalent to:
q){z+x*y}\[0;indices;indices]
0 1 0 1 0 0 1 2 0 1
What this is doing is essentially using the booleans as an on/off switch (via the boolean multiplication) for the rolling sum. It adds (z+) until it hits a negative boolean in which case the rolling sum resets back to zero.
In english: nextValue + [currentValue (starting at 0) * nextValue]
When nextValue is 1, 1 gets added. When nextValue is 0 the result is zero (resetting the rolling sum).
Something like this can achieve the same thing, though no less easy to read at a glance (and using two scans instead of one):
q){s-maxs not[x]*s:sums x}indices
0 1 0 1 0 0 1 2 0 1i
Terry has answered your question about how runs works.
Comparing adjacent items is common. You might prefer to use the prior keyword. Certainly easier to see what it is doing.
q)where (and) prior indices
,7

System Dynamics simulation - Translating Stella into AnyLogic syntax

I modelled the following logic in stella:
(IF "cause" > 0 THEN MONTECARLO("probabilityofconsequence") ELSE 0
But Im not getting the correct syntax on AnyLogic:
(cause > 0) ? (uniform() < probabilityofconsequence) ? 1 : 0 : 0
Any ideas?
Disclaimer:
What stella does is with the Montecarlo function a series of zeros and ones from a Bernoulli distribution based on the probability provided. The probability is the percentage probability of an event happening per DT divided by DT (it is similar too, but not the same as, the percent probability of an event per unit time). The probability value can be either a variable or a constant, but should evaluate to a number between 0 and 100/DT (numbers outside the range will be set to 0 or 100/DT). The expected value of the stream of numbers generated summed over a unit time is equation to probability/100.
MONTECARLO is equivalent to the following logic:
IF (UNIFORM(0,100,<seed>) < probability*DT THEN 1 ELSE 0
the equivalent in anylogic should be:
cause>0 && uniform(0,100) < probability*DT ? 1 : 0
you need to create a variable called DT that is the equal to either the fixed time step that you have chosen in your model configuration, or the value you consider that should be adequate.
Since anylogic depending on how you are running the model, doesn't consider the fixed time step as fixed, you need to define the DT yourself.
No matter what, you are going to get results not exactly equal to stella probably since the time steps are not necessarily the same... but maybe similar enough should satisfy you

Generate prime numbers recursively, Matlab

I am trying to generate prime numbers recursively using the previous primes. 2 is a prime by default and each time I keep adding 1 to the next number and divide by the previous primes, eg 2+1=3 so i check that 2 does not divide 3 so 3 is prime so i store 2 and 3 so far, next would be 3+1=4, i would use my current prime list 2 and 3, and see that 2 divides 4 so it does not go into the list then i continue with 4+1 and so forth all the way up to n. The key thing is dividing by the previous primes each time and if you reach a prime the list is updated. Please check my program to see what i am doing wrong.
this is my program so far but I am just getting 3 and 962, i want it update the list and refer back to it each time for the loop so i can use mod(2+numba,primlist) each time:
n=960;
primlist=[];
for numba=2:n
if mod(2+1,2)~=0
primlist=2+1;
end
if mod(2+numba,primlist)~=0
primlist=[primlist;2+numba];
end
end
primlist
You are initializing your primlist again and again. Do not do that. I am making as less modifications to your code to make it run correctly. The logic is essentially correct. You just need to initialize primlist outside.
n=960;
primlist=2;
for numba=1:n %Changed 2 to 1
if mod(2+numba,primlist)~=0
primlist=[primlist;2+numba];
end
end
primlist

Finding 5 consecutive successes using Matlab?

I have a function which for 10 cycles finds the difference between individual sensor values and the average sensor value. The test will be done 100 times using this function. So every time cycle>10 I am forcing it to be zero so that in the 11th repetition it will restart counting from zero. Here is the code:
cycle=cycle +1;
if cycle>10
cycle=0;
end
for i=1: TotalnoOfGrids
for j=1: noOfNodes
if abs(char(Allquants{i}(j))-char(mostCommonLetters {i}))>0
if cycle>0
wrong{i}(j)=wrong{i}(j)+1;
else
wrong{i}(j)=0;
end
end
end
end
Now I need to know if the sensor performed 5 consecutive successes in the period of 10 cycles. How can I do that?
I thought of a loop but I read that it takes too much time.
Doing a search on the net I have found this SO question.
The problem is that the above function will be repeated for 100 cycles.I want for every 10 cycles see if there is consecutive successes so it is beeing done dynamically and I am not saving the success or failure status of the sensor for the cycles. So i do not have a vector containing 1 or 0 to use the function used in the above reference or as Jonas suggested
If a loop is the easiest thing, give it a try! Just because you've read it "takes too much time" doesn't mean it really makes a difference for your case! It is true that in Matlab it often makes sense to avoid loops; but in your case, 100*20*9 (if I understand you correctly) loop iterations doesn't seem so bad yet (depending on your speed requirement).
Edit (corrected answer)
I now understand from your comments that the code you show us is surrounded by a while or for loop which is being run ~100 times, and that Allquants and mostCommonLetters probably change inside that loop. In this case my previous answer didn't work for you, since it counted successes on different sensors; this should be better now.
If I read your code correctly, the condition abs(char(Allquants{i}(j))-char(mostCommonLetters {i}))>0 tells you that a result was "wrong"; consequently,
for i=1:TotalnoOfGrids
this_cycle_successes(i,:)=char(Allquants{i})==char(mostCommonLetters{i});
end
consecutive_successes=(consecutive_successes+1).*this_cycle_successes;
would calculate how many successes you had in a row. Note you need to initialize consecutive_successes before starting your cycle loop, e.g.
consecutive_successes = zeros(9,20);
After the 10 cycles, you can check which sensors had 5 successes like this:
has5successes = consecutive_successes>=5;
Note that this is a matrix operation, so now you will get 9*20 values, as you requested in your comment. This solution wouldn't require a loop over j.