Change in source :Agents per arrival and Maximum number of arrival at runtime - anylogic

I am modeling a manufacturing system. The case is that I would like to implement a ramp-up model so the Agents per arrival and Maximum number of arrival change at a specific time during the simulation.
I tried to implement this by using an event but then I am not able to actually change the values of the source.

Change your source arrivals to be defined by calls of inject() funtion.
Use a cyclic event with a reccurence time of 1. That will reflect your interarrival time.
Then use an if statement to control your maximum arrivals.
if (source.count() < maxArrivals) {
source.inject(agentsPerArrival);
}

Maximum number of arrivals is a static parameter, you can't change it during runtime like that. (Check out the icons in front of the edit boxes: Agents per arrival has an arrow, showing that it's dynamic and Maximum number of arivals has an equal sign)
You can call towerFactory.set_maxArrivals(145/towerRatio) in your event, but it will only take effect if the Source has not reached the previously set number of arrivals yet. If that is the case, you need to take a different approach.

Related

Get the same arrival rate across models

I have a model that I have duplicated and made some adjustments to it. When I run both models with the same fixed seed I don’t get the same results, which I understand because I have other sources of randomness in the model. Regardless, in both models, I am using a source block, such that the arrivals are defined by a rate schedule, the schedule is of type rate, and is provided from the database. Now, I know the following pieces of information:
Generally, I can use my own random number generator (RNG) in distributions, for example triangular(5, 10, 25, myRNG), such that Random myRNG = new Random (2)
By default, a schedule with “type” rate follows a passion distribution that utilizes the default RNG.
At anytime in the model, I can substitute the default RNG with my own by calling setDefaultRandomGenerator(Random r).
The question is: Is it possible to use a fixed seed for the arrival rate to make sure I am getting the same exact input in both models?
In anylogic, rates are always equivalent to a poisson distribution with lambda equal to the rate you set,
Intearrival times don't follow any distribution, but using exponential(lambda) in the field is equivalent to using a arrival by rate with a rate of lambda.
But poisson and exponential are closely related, which is why if you use poisson(1.0/lambda) in the intearrival time, you have the same average arrivals as if you use exponential(lambda).
It is not possible to set a seed for the arrival rate, and that's why you need to use intearrival times instead in your source
But you need to create a variable first, let's call it rand, of type Random with initial value new Random(seed)
where seed is any integer you want (long to be more exact)
then in the intearrival time you need to do:
exponential(lambda, 0,rand)
This will lead to unique simulation runs, no matter what configuration you have in the AnyLogic experiment
Sure, simply set both Source blocks to "Interarrival time" in the "arrivals defined by".
Then, use the same code poisson(1, myRNG) in the field, making sure that the myRNG RNG uses the same initial seed (i.e.new Random(1234)
(the "Rate" setting is the same as using poission(1) for interarrival-time)

Using varying lambda with interarrival time while receiving same arrivals across models

I have learned from my previous question “Get the same arrival rate across models” that for two models with the same arrival rate input, I can get the exact same arrivals generated in both models by setting the source block in both to “Interarrival time” and in the code, use exponential(lambda, 0, rand) where rand is a user-defined random number generator (RNG), for example, Random rand = new Random(1234). If prior to setting the source block to “Interarrival time” I had it set to “Rate Schedule” in which the schedule is of type rate that is provided from the database and in my case the rate (lambda) is not constant, it depends on the time of the day, how can I overcome this when setting the source block to “Interarrival time”?
Since it is not possible to set a seed for the arrival rate, you'll need to use interarrival times instead in your source.
However, since you also need to vary the interarrival time based on the time of day, you should write a function that returns different exponential random variables depending on the time of day and use that as your interarrival times.
Here is how I did that in AnyLogic:
And I made a quick plot of how many injections were occurring per hour just to verify that the rates are actually changing.
Perhaps I'm understanding the question wrong, but interarrival times can these not be transformed to arrival rate, so for example if interarrival time = 2minutes, the arrival rate is 0.5 per minute. If this is the case for your model, you can use in the source block arrivals defined by: a rate schedule (as shown in the figure below.)
After that in the schedule you can change the different arrival rates, so for example between 00:00 and 01:00 the arrival rate should be 1 as shown in the figure below:

Reactive Extensions rate of change detection from normal movement

Given a sequence of numbers that trend overtime, I would like to use Reactive Extensions to give an alert when there is a sudden absolute change spike or drop. i.e 101.2, 102.4, 101.4, 100.9, 95, 93, 85... and then increasing slowly back to 100.
The alert would be triggered on the drop from 100.9 to 95, each would have a timestamp looking for an an alert of the form:
LargeChange
TimeStamp
Distance
Percentage
I believe i need to start with Buffer(60, 1) for a 60 sample moving average (of a minute frequency between samples).
Whilst that would give the average value, I can't assign an arbitrary % to trigger the alert since this could vary from signal to signal - one may have more volatility that the other.
To get volatility I would then take a longer historical time frame Buffer(14, 1) (these would be 14 days of daily averages of the same signal).
I would then calculate the difference between each value in the buffer and the 14 day average, square and add all these deviations, and divide by the number of samples.
My questions are please:
How would I perform the above volatility calculation, or is it better to just do this outside of RX and update the new volatility value once daily external to the observable stream calculation (this may make more sense to avoid me having to run 14 days worth of 1 minute samples through it)?
How would we combine the fast moving average and volatility level (updated once per day) to give alerts? I am seeing Scan and DistinctUntilChanged on posts on SO, but cant work out how to put together.
I would start by breaking this down into steps. (For simplicity I'll assume the original data source is an observable called values.)
Convert values into a moving averages observable (we'll call this averages here).
Combine values and averages into an observable that can watch for "extremes".
For step 1, you may be able to use the built-in Window method that Slugart mentioned in a comment or the similar Buffer method. A Select call after the Window or Buffer can be used to process the array into a single average value object. Something like:
averages = values.Buffer(60, 1)
.Select((buffer) => { /* do average and std dev calcuation here */ });
If you need sliding windows, you may have to implement your own operator, but I could easily be unaware of one that does exist. Scan along with a queue seem like a good basis for such an operator if you need to write it.
For step 2, you will probably want to start with CombineLatest followed by a Where clause. Something like:
extremes = values.CombineLatest(averages, (v, a) => new { Current = v, Average = a })
.Where((value) = { /* check if value.Current is out of deviation from value.Average */ });
The nice part of this approach is that you can choose between having averages be computed directly from values in line like we did here or be some other source of volatility information with minimal effect on the rest of the code.
Note that the CombineLatest call may cause two subscriptions to values, one directly and one indirectly via a subscription to averages. If the underlying implementation of values makes this undesirable, use Publish and RefCount to get around this.
Also note that CombineLatest will output a value each time either values or averages outputs a value. This means that you will get two events every time averages updates, one for the values update and one for the averages update triggered by the value.
If you are using sliding windows, that would mean a double update on every value, and it would probably be better to simply include the current value on the Scan output and skip the CombineLatest altogether. You would have something like this instead:
averages = values.Scan((v) => { /* build sliding window and attach current value */ });
extremes = averages.Where((a) => { /* check if current value is out of deviation for the window */ });
Once you have extremes, you can subscribe to it and trigger your alerts.

Is there a way to record when (and how often) Transporters get within a certain distance of each other?

I have an AnyLogic simulation model using trucks and forklifts as agents (Transporter type), and among other things would like to identify each time one of them becomes within a certain distance of another one (example within 5 meters). I will record this count as a variable within the main space of the model. I am using path-guided navigation.
I have seen a method "agentsInRange" which will probably be able to do the trick, but am not sure where to call this from. I assume I should be able to use the AL functionality of "Min distance to obstacle" (TransporterFleet) and "Collision detection timeout" (TransporterControl)?
Thanks in advance!
Since there don't seem to be pre-built functions for this, afaik, the easiest way is to:
add an int variable to your transporter agent type counter
add an event to your transporter type checkCollision that triggers every second or so
in the event, loop across the entire population of transporters and count the number that are closer than X meters (use distanceTo(otherTransporter) and write your own custom code)
add that number to counter
Note that this might be very inefficient computationally as it is quite brute-force. But might be good enough :)

Simulation: send packets according to exponential distribution

I am trying to build a network simulation (aloha like) where n nodes decide at any instant whether they have to send or not according to an exponential distribution (exponentially distributed arrival times).
What I have done so far is: I set a master clock in a for loop which ticks and any node will start sending at this instant (tick) only if a sample I draw from a uniform [0,1] for this instant is greater than 0.99999; i.e. at any time instant a node has 0.00001 probability of sending (very close to zero as the exponential distribution requires).
Can these arrival times be considered exponentially distributed at each node and if yes with what parameter?
What you're doing is called a time-step simulation, and can be terribly inefficient. Each tick in your master clock for loop represents a delta-t increment in time, and in each tick you have a laundry list of "did this happen?" possible updates. The larger the time ticks are, the lower the resolution of your model will be. Small time ticks will give better resolution, but really bog down the execution.
To answer your direct questions, you're actually generating a geometric distribution. That will provide a discrete time approximation to the exponential distribution. The expected value of a geometric (in terms of number of ticks) is 1/p, while the expected value of an exponential with rate lambda is 1/lambda, so effectively p corresponds to the exponential's rate per whatever unit of time a tick corresponds to. For instance, with your stated value p = 0.00001, if a tick is a millisecond then you're approximating an exponential with a rate of 1 occurrence per 100 seconds, or a mean of 100 seconds between occurrences.
You'd probably do much better to adopt a discrete-event modeling viewpoint. If the time between network sends follows the exponential distribution, once a send event occurs you can schedule when the next one will occur. You maintain a priority queue of pending events, and after handling the logic of the current event you poll the priority queue to see what happens next. Pull the event notice off the queue, update the simulation clock to the time of that event, and dispatch control to a method/function corresponding to the state update logic of that event. Since nothing happens between events, you can skip over large swatches of time. That makes the discrete-event paradigm much more efficient than the time step approach unless the model state needs updating in pretty much every time step. If you want more information about how to implement such models, check out this tutorial paper.