cs4ec / CS4EC_DSL

MIT License
1 stars 0 forks source link

runtime-evaluated conditionals in Behaviours #33

Closed thomasGodfrey closed 2 years ago

thomasGodfrey commented 3 years ago

We currently have Behaviours which are methods agents can perform, consisting of ActionSteps. Behaviours can contain conditionals that determine what branches' of ActionSteps are performed based on some set condition (e.g. patient is symptomatic or not). The problem is that the evaluation of these conditionals happen as soon as an agent starts the Behaviour. So, for example, for a Behaviour 'Test patient', with action steps (1) Test patient with testA, (2) if test positive do x, if negative do y. This would not currently be possible as the conditional depends on testA having been completed - but this check was performed before the agent actually performs ActionStep(1)! Instead, the conditional check should happen at the time that the agent starts ActionStep(2). This is primarily an issue of how Behaviours are constructed in the code. Currently it is just a single method which adds ActionSteps to the behaviour line by line. My idea is to flesh out the ActionSteps, such that theseConditionals' become their own object with distinct lists of ActionSteps that are added to the current Behaviour depending on the condition evaluation at the point the conditional is met in the Behaviour. So following the above example, a `TestCondition' object will be made, with an evaluate() method. On calling this method, If the condition evaluates to true, then the relevant ActionSteps will be injected into the Agent's Behaviour - and if false, an alternative list of ActionSteps will be injected.

szschaler commented 3 years ago

Is there actually a need to have behaviour steps as objects in the Repast code at all? Could you not simply generate corresponding Java code directly? So, rather than generating an object structure describing the behaviour that is then interpreted by some generic interpretation code as the simulation runs, simply generate Java code that is compiled and executed as part of the simulation.

thomasGodfrey commented 3 years ago

I think I see what you mean, however, I have recently been dealing with behaviours such that an agent can be doing multiple behaviours at once. For example, a doctor can be waiting for test results as part of one behaviour whilst giving a history check for a different patient as part of another behaviour. It then becomes helpful to have these as objects because they can be kept in a list by the agent, and be iterated through independently. Perhaps I am misunderstanding what you mean though

szschaler commented 3 years ago

I see. So there is some benefit to reifying the behaviours as objects, but that doesn't mean they need to be made from pre-implemented building blocks. You could simply use a Runnable (or a more specific interface) and then generate specific behaviours as inner classes in a generated agent class. You could then still schedule these behaviour blocks at simulation runtime...

thomasGodfrey commented 3 years ago

Hi Steffen, I have been ruminating on this for a few days and I am getting a bit lost. So to make sure I understand correctly...

For every Behaviour in my ED-DSL, I would generate a 'Behaviour' object. For every BehaviourStep inside that Behaviour, I would generate an inner class corresponding to some schedulable interface inside the relevant Agent class. E.g. If I have a Behaviour for a Nurse = 1) Go to Triage, 2) Wait 3 minutes Then in my generated Nurse class, I generate an inner class 'GoToTriage' and another inner class 'WaitThreeMinutes' that define exactly what the agent needs to do in each step (i.e. no generic interpretable object, just actual code). I then also generate a 'Behaviour' object which contains in it a list of those two generated class objects? {new GoToTriage(), new WaitThreeMinutes()} ?

When an Agent goes to execute their behaviour, they then just take the Behaviour object, check what step they are currently on, and call the 'execute()' method of the relevant inner class.

Is that about correct?

szschaler commented 3 years ago

Not sure I know enough about the Repast internals to give a really useful answer here. To me, this sounds correct, but your description also seems to have lost the actual conditionals...

thomasGodfrey commented 3 years ago

okay great, that was actually what I wanted to lead on to. If the structure sounds right, my idea was to have conditionals as their own inner class again.... So that when the agent comes to do the behaviour, and reaches the relevant step, they would still call the 'execute()' method of that conditional inner class. This would then cause the condition to be evaluated at the correct time, and as a result of the outcome, a new set of behaviourSteps would be injected into the agent's current Behaviour

So with the example above, after GoToTriage and WaitThreeMinutes there could be a BehaviourStep like 'IsPatientSevere' which is its own inner class again, and contains code like : 'if(patient.Severity()==High) { Behaviour.inject(new GoToMajorsC()); } else { Behaviour.inject(new GoToMajorsAB()); }

The idea being that once this conditional statement is evaluated, the current overall Behaviour that the agent is performing will have new steps added into it depending on the outcome of the conditional. (I hope that makes sense)

szschaler commented 3 years ago

That sounds right to me

thomasGodfrey commented 2 years ago

Done