Dynamic Event to release pallet types with specified ID to the time of a dbase - anylogic

I would like to use the loop trough my dbase and create_mydynamicevent in MAIN for different process flows. So by means of my dynamic event I will release the type of pallets (id) to specified times which I insert into my source block. Because of that I can use my create_mydynamicevent function for different processes. My question is either what is wrong at the myDE and should I also adapt the create_dynamicevent function in Main?
Agent Type: Pallet: agent.typeID = pallet types
n = number of pallets I would like to release to the specified time of the dbase
flowchart Agent Type = Pallet
My Dynamic event and wait block are in my custom flowchart Agent Type "Store_and_Pick"
Main to create the dynamic event:
List< Tuple > amounts =selectFrom( tor77_kunde1 ).list();
for( Tuple tup : amounts ) {
Date today=date();
Date future=tup.get(tor77_kunde1.picktime);
long diff = future.getTime() - today.getTime();
int n =tup.get(tor77_kunde1.n);
process.create_MyDynamicEvent(diff, MILLISECOND, n);
process1.create_MyDynamicEvent(diff, MILLISECOND, n);
}

Related

infinite value while using cumulative constraint

I am stuck with a cumulative constraint I seem not to use properly, I seek for help ! :)
I have tasks with precedence and, for some of them, required & forbidden resources.
I need to decide when to start a task & who to assign to it.
To do so, I'm using an array of decision variable resource_allocation:
array[Tasks, Resources] of var 0..1: resource_allocation; %Selection of resources per task.
To manage the required/forbidden resources, I used the following:
% Mandatory & Forbidden constraint allocation
constraint forall(t in Tasks, r in resource_required[t])(resource_allocation[t,r]=1);
constraint forall(t in Tasks, r in resource_forbidden[t])(resource_allocation[t,r]=0);
resource_required being set of int storing the resources number that are required/forbidden.
Each resource represents 1 worker, and each worker can only perform one task at a time, so I am trying to state that, for every resources, the cumsum of allocation can at max be 1.
It might be important to note that start is also a decision variable.
% Constraint allocated to only one task at a time
constraint forall(t in Resources)(
cumulative(start, duration, [resource_allocation[t, r] | t in Tasks], 1)
);
Doing so, I always end up with the following error
JC:70.12-82
in call 'cumulative'
cumulative:21-3.49-7
in binary '/\' operator expression
cumulative:25-3.49-7
in if-then-else expression
cumulative:26-5.48-9
in binary '/\' operator expression
cumulative:30-5.48-9
in if-then-else expression
cumulative:47.7-32
in call 'fzn_cumulative'
fzn_cumulative:4-9.20-17
in let expression
fzn_cumulative:8-13.20-17
in if-then-else expression
fzn_cumulative:10-17.19-17
in let expression
fzn_cumulative:12.21-74
in variable declaration for 'late'
in call 'max'
with i = <expression>
MiniZinc: evaluation error: arithmetic operation on infinite value
Process finished with non-zero exit code 1.
I need a little guidance, I looked in the source code of fzn_cumulative, but I don't get what is going on.
Thanks !
You might consider to limit the domains of your decisions variables.
int is unlimited (disregarding the limited number of bits per int) and may lead to overflow situations or complaints about infinite values.
include "globals.mzn";
set of int: Tasks = 1..3;
set of int: Resources = 1..3;
set of int: Durations = 1..10;
set of int: Times = 1..1000;
% Use this editor as a MiniZinc scratch book
array[Tasks, Resources] of var 0..1: resource_allocation; %Selection of resources per task.
array [Tasks] of var Times: start;
array [Tasks] of var Durations: duration;
array [Tasks] of set of Resources: resource_required = [{1,2},{2,3},{3}];
array [Tasks] of set of Resources: resource_forbidden = [{},{1},{1}];
% Mandatory & Forbidden constraint allocation
constraint forall(t in Tasks, r in resource_required[t])(resource_allocation[t,r]=1);
constraint forall(t in Tasks, r in resource_forbidden[t])(resource_allocation[t,r]=0);
% Constraint allocated to only one task at a time
% Changed "t in Resources" to "r in Resources"
constraint forall(r in Resources)(
cumulative(start, duration, [resource_allocation[t, r] | t in Tasks], 1)
);

Insert an ID into the loop trough my dbase

I would like to use the loop trough my dbase and create_mydynamic event in MAIN for different process flows. I have to insert a function where it will only pick the pallets with the specified ID. So the different pallet types (ID) which I insert into my process with the source block should have the same ID like the pallets I will pick based on my database. So something like that:
agent.typeID= tor77_kunde1.id
Can you help me if it is possible?
List< Tuple > amounts =selectFrom( tor77_kunde1 ).list();
for( Tuple tup : amounts ) {
Date today=date();
Date future=tup.get(tor77_kunde1.picktime);
long diff = future.getTime() - today.getTime();
int n =tup.get(tor77_kunde1.n);
process.create_MyDynamicEvent(diff, MILLISECOND, n);
process1.create_MyDynamicEvent(diff, MILLISECOND, n);
}
Currently, you are freeing the last agent in the "wait" object. You need to free the one that has typeID == n in your DE.
So change your loop to something like:
for (MyAgentTypeWaitingInWait currentAgent : wait.getAgent()) {
if (currentAgent.typeID == n) {
wait.free(currentAgent);
break;
}
}
MyCurrentAgentType is the type of the agents waiting in "wait". (Uppercase!). Read on the "enhanced for-loop" as well to understand better

AnyLogic change parameter value at a process

In AnyLogic Simulation software, I have an agent that has some parameters. I just want that whenever this agent passes from a specific process, say delay, its parameter value to be changed to another value. Moreover, if I have 100 individuals (all same type of agents) passing from this process, I will change the first 40 of these individuals' parameter values to 1, and the last 60's values to 2. Is this possible? Do I need to write codes to these boxes:
Yes, you have to write some code on one of these boxes.
Create an integer variable named v_countand set the initial value to 0. If you want agent's parameters to be changed as soon as they enter the block write this code "On enter" box, else if you want them to be changed when they leave the block write it "On at exit":
if(v_count < 40)
agent.parameter = value1;
else
agent.parameter = value2;
v_count++;
//reset the count to 0 when 100 agents have passed through this block
if(v_count == 100)
v_count = 0;

I want to convert from Point to Agent that gives me proper location

I am working on agent-based modelling where I have created a function that generates a random point inside a region and then converts that point to agent. However, when I use this function later, the points don't give me a proper location on the map for further computation. I want to know what I am doing wrong? Or how can this be improved.
The return type for the function is ArrayList
ArrayList<DeliveryHouse> House = new ArrayList<DeliveryHouse>();
int i;
Point p;
DeliveryHouse h;
for(i=0;i<packagesC2C;i++)
{
p = main.Region2.randomPointInside();
h = main.deliveryHouse.setLocation(p);
House.add(i, h);
};
return House;
The major problem I see with your code is that you are not initializing the agent "h" but pointing it to one agent you have at main which means you keep changing its location in the loop and it will only reflect the last location. The array list you created will have multiple references to same agent instead of one agent per location.
If you want to create an agent per location you need to create an agent population called "deliveryHouses" of the agent type "DeliveryHouse" and change your code to the following. Note that the population will have all the agents so you do not need any output from the function.
int i;
Point p;
for(i=0;i<packagesC2C;i++)
{
DeliveryHouse h = main.add_deliveryHouses();
p = main.Region2.randomPointInside();
h.setLocation(p);
}

Q: [Anylogic] Measuring production throughput rate

I would like to know how to measure the throughput rate of the production line on Anylogic.
Question: Are there any methods to measure the Time Between Departure of the agent at the sink block? >>(I will calculate the throughput rate by inverting the time between departure value.)
At the moment, I just simply calculated the throughput based on Little's law, which I use the average lead time and WIP level of the line. I am not sure that whether the throughput value based on this calculation will be equal to the inverted value of the time between departure or not?
I hope you guys could help me figure it out.
Thanks in advance!
There is a function "time()" that returns the current model time in model time units. Using this function, you may know the times when agent A and agent B left the system, and calculate the difference between these times. You can do this by writing the code like below in the "On exit" field of the "sink" block:
statistic.add(time() - TimeOfPreviousAgent);
TimeOfPreviousAgent = time();
"TimeOfPreviousAgent" is a variable of "double" type;
"statistic" is a "Statistic" element used to collect the measurements
This approach of measuring time in the process flow is described in the tutorial Bank Office.
As an alternative, you can store leaving time of each agent into a collection. Then, you will need to iterate over the samples stored in the collection to find the difference between each pair of samples.
Not sure if this will help but it stems off Tatiana's answer. In the agents state chart you can create variables TimeIn, TimeOut, and TimeInSystem. Then at the Statechart Entry Point have,
TimeIn = time();
And at the Final state have,
TimeOut = time();
TimeInSystem = TimeOut - TimeIn;
To observe these times for each individual agent you can use the following code,
System.out.println("I came in at " + TimeIn + " and exited at " TimeOut + " and spent " + TimeInSystem + " seconds in the system";
Then for statistical analysis you can calculate the min, avg, and max throughputs of all agents by creating in Main variables, TotalTime, TotalAgentsServiced, AvgServiceTime, MaxServiceTime, MinServiceTime and then add a function call it say TrackAvgTimeInSystem ... within the function add argument NextAgent with type double. In the function body have,
TotalTime += NextAgent;
TotalAgentsServiced += 1;
AverageServiceTime = TotalTime/TotalCarsServiced;
if(MinServiceTimeReported == 0)
{
MinServiceTime = NextAgent;
}
else if(NextAgent < MinServiceTime)
{
MinServiceTime = NextAgent;
}
if(NextAgent > MaxServiceTime)
{
MaxServiceTime = NextAgent;
}
Then within your agent's state charts, in the Final State call the function
get_Main().TrackAvgTimeInSystem(TimeInSystem);
This then calculates the min, max, and average throughput of all agents.