I have an agent that is nested in another agent. This nested agent has a function that calls the annylogic probability distribution functions(pdfs) such as gamma(), lognormal(), etc. However I keep getting a nullPointerException if I call these pdfs inside the nested agent. I am realising this is because the nested agent cannot access the default randomNumberGenerator. Is there a way I can access the defaultRandomNumberGenerator within the nested agent as well or is the only solution to create a new generator for each nested agent?
The error is because your agent is outside the model hierarchy of agents.
This is not good practice; there should very rarely be a need to have 'floating' agents outside the model hierarchy; they can always be inside an agent population somewhere.
In the rare cases that there are strong design reasons to do so (or if you use plain Java classes and thus have Java objects which by definition are not Agents and are therefore outside the agent hierarchy), just give them a parameter (field in the case of a Java class) that points to some agent that is in the model hierarchy (typically their 'generator'), and then you can call all 'required-to-be-in-model-hierarchy' functions via that parameter. (That is, you are delegating all such calls to an agent instance which can call them.)
e.g., the nested agent type (let's say Thing) has parameter agentRef of type Agent set by whoever creates it; for example
Thing t = new Thing(this);
Then, within Thing, you use code such as agentRef.normal(1,10).
Only agents that are connected to the engine in some way have access to the random number generator. And if your experiment is set to run main - like the example below - then all agents that want to use the random number generator must be connected to main in some way
So if you do this for example it wont work, and you get an NPE (Null Pointer Exception)
If you do this it will
Best option is to just create your own random number generator
lognormal(0.1, 0.1, 5, new Random(0));
(Just put the random number generator somewhere so that you can use it again and again, else you will get the same number every time since it is the same (new) random object used to get the number)
This design is way better - see example here
Why do two flowcharts set up exactly the same end with different results every time the simulation is run even when I use a fixed seed?
Related
This is about an API handling the validation during saving an object. Which means that the front-end client sends a request to the API to a specific end point, then on the back-end the API creates a new object if the right conditions are meet.
Right now the regular method that we use is that the models has a ruleset for each fields and then the validation is invoked when the save function is invoked, but technically the validation is done right before the object is saved into the database.
Then during today's code review I came across a solution which I wasn't sure if it's a good practice or not. And it was about that the front-end must send a specific parameter to the API every time. This is because other APIs are using our API as well, and we needed to know if the request was sent as and API request or a browser request. If this parameter is present then we want to execute an extra validation function on a specific field.
(1)If I would have to implement it, then I would check the incoming parameter in the service handler or in the controller level, and if I got one, I would invoke the validation right away, and if it fails I would throw an error.
(2)The implementation I saw however adds an extra variable to the model, and sets the model variable when there is an incoming parameter, then validates only when the save function is invoked on the object(which first validates the ruleset defined on the object fields, then saves the object into the database)
So my problem with (2) is that the object now grown bigger with an extra variable that is only related to a specific event. So I would say it's better to implement (1). But (2) also has an advantage, and that is when you create the object on different end point by parsing the parameters, then the validation will work there as well, even if the developer forget to update the code there.
Now this may seems like a silly question because, why would I care about just 1 extra variable, but this is like a bedrock of something good or bad. So if I say this is ok, then from now on the models will start growing with extra variables that are only related to specific events, which I think should be handled on the controller/service handler level. On the other hand the code would be more reliable if it's not the developer who should remember all the 6712537 functionalities and keep them in mind when makes some changes somewhere. Let's say all the devs will get heart attack tomorrow from the excitement of an amazing discovery, and a new developer has to work on the project while he doesn't know about these small details, and then he has to change something on the code that is related to this functionality - so that new feature should be supported by this old one as well.
So my question is if is there any good practice on this, and what do you think what would be the best approach?
So I spent some time on thinking on the solution, and I think the best is to have an array of acceptable trigger variables in the model class. Then when the parameters are passed to the model on the controller level, then the loader function can be modified that it takes the trigger variables from the parameters and save it in the model's associative array variable that stores the trigger variables.
By default this array is empty, and it doesn't matter how much new variables are needed to be created, it will only contain the necessary ones when those are used.
Then of course the loader function needs to be modified in a way that it can filter out the non trigger variables as well as it is done for the regular fields, and there can be even a rule set of validation on the trigger variables if necessary.
So this solves the problem with overgrowing the object with unnecessary variables and the centralized validation part, because now the validation can be always done in the model instead of the controller.
And since the loader function is modified to store the trigger variables in the model's trigger variables array variable, the developer never has to remember that this functionality was created. Which is good, because in the future when he creates a new related function or end point that should handle object creation, he will not miss it to validate it against the old functionality, because the the loader function that he modified in the past like this will handle it for him.
It needs to be noted tho, that since the loader function doesn't differentiate between the parameters, and where to load them other then checking the names of the parameters with the filter functions, these parameter names should be identical from each other, otherwise a buggy functionality can be created accidentally. Like if you forget that a model attribute with the same name was used, then you can accidentally trigger an event that was programmed to be triggered if the trigger variable with the same name is present. However this can be solved by prefixing the trigger variables for example.
I am an Engineering Student and as part of my diploma thesis, I am simulating the passenger changeover process in metros using the Anylogic Pedestrian Library.
In the simulation, it often happens that standing passengers "leave" the standing area and somehow get into the sitting places, blocking the way from other peds that would like to occupy the seat.
All passengers come from the Passenger Agent, where they have a boolean variable wantToSit. If wantToSit = false, they are routed into the standing area, with wantToSit = true they go to take their seats.
Now, I would like to restrict the access of peds with wantToSit = false into the area drown using polygonal nodes around the seat groups, so that the phenomenon written above cannot occur, thus only sitting passengers will enter this area.
However, when I try to define the condition for the access restriction in the polygonal Node, I always get the error "... cannot be resolved to a variable".
Here is the variable from the Agent "Passenger":
On the Agent "Main", where the Polygonal Node is, the auto code complete does not recommend anything for want or for ped. . For the word Passenger, see the picture below:
Is there a way to use the access restriction feature in this case? I don't know how to access this parameter of Passenger from Main, which is a different agent.
Thank you in advance for your help!
If you do the code complete action in the condition field before you type anything, you will see that the local variables available for you to use in the condition field is agent and self
And then if you choose agent you will see that the fields within your custom Pedestrian agent will become available.
Try not to type anything without code complete. It can save you a lot of time.
I would like to create a kind of a "smart" MoveIteratorFactory for my VRP (time windowed) example based app. This move factory should return an Iterator that would generate each time a CompositeMove based on the current solution state.
Is it possible for the MoveIteratorFactory to create an Iterator that generates moves based on current solution state?
AFAIK MoveIteratorFactory's methods accept a ScoreDirector object, and it seems that the returned Iterator should generate moves using instances retrieved from the ScoreDirector's working solution. But are these instances being updated while the solver process is undergoing? Do they have all planning variables set according to the current working solution state, when hasNext and next methods are called? Or should an iterator have a field with a ScoreDirector instance, and generate moves using instances retrieved each time from the ScoreDirector?
Yes, just make sure sure that the cacheType isn't PHASE or higher (by default it's fine because by default it's JUST_IN_TIME). See docs chapter 7.
At the beginning of every step it will call createRandomMoveIterator(), which can take into account the state of the current workingSolution.
I have a process diagram that directs flow on the basis of threshold variables. For example, for variable x,y; if x<50 I am directed to service task 1 , if y<40 to service task 2, or if x>50 && y>40 to some task..
As intuition tells, I am using compare checks on sequence flow to determine next task.
x,y are input by user but 50, 40 (Let's call these numbers {n}) is a part of process definition(PD).
Now, for a fixed {n} I have deployed a process diagram and it runs successfully.
What should I do if my {n} can vary for different process instances? Is there a way to maintain the same version of process definition but which takes {n} dynamically?
I read about BPMN Model API here. But, I can't seem to figure out how to use it to edit my PD dynamically? Do I need to redeploy it each time on Tomcat or how does it work?
If you change a process model with the model API you have to redeploy it to actually use it. If you want to have a process definition with variable {n} values you can also use a variable for it and set it during the start of the process instance either using the Java API, REST API or the Tasklist.
I am modeling a complex process using BPMN 2.0
I have split the process into multiple global processes which can reference one another through call activity.
However, in one or two special cases, I would like to actually call directly into the middle of one of the other processes. I do not want to have to create an entirely duplicate [sub]process with just the first couple nodes missing and would also prefer not to split those couple nodes into their own little process.
I don't think common BPMN 2.0 tools support this, but is it explicitly disallowed by the spec? For instance, I read through http://www.omg.org/spec/BPMN/2.0.2/PDF and I don't see anywhere that it claims that a sequenceFlow's targetRef must be within the same FlowElementsContainer. Maybe it is just implied?
The correct way to do this would be to create several "none" start events in the global process and then reference the correct one via the targetRef attribute of a sequence flow incoming to the call activity. The spec says on p. 239:
"If the Process is used as a global Process (a callable Process that
can be invoked from Call Activities of other Processes) and there are
multiple None Start Events, then when flow is transferred from the
parent Process to the global Process, only one of the global Process’s
Start Events will be triggered. The targetRef attribute of a Sequence
Flow incoming to the Call Activity object can be extended to identify
the appropriate Start Event."