This chapter documents arguments and reasons for (and against) specific implementations. Headers like "Stage A" name paragraphs which describe past implementation. Note that their nomenclature may not correspond to the recent one.
Behavioural Options should be immutable:
Since behavioural options can be semantically grouped into certain classes and furthermore follow a hierarchy, in most cases it is useful to reflect this hierarchy in the implementation. This way, routines for checking applicability of options could be generalised.
Four tables are useful:
Issues: [[*]] How to we store utilities values in DB for BO? Problem: number of preferences is dynamic....
For more complicated checking processes this procedure is overwritten
Situational preferences for a certain decision may depend on the execution of another decision, i.e. decision A changes an environmental property that influences the current preference value that is required for another decision B. I.e., calculating current preferences at the beginning of a time cycle may not be sufficient. Furthermore, in case of parallel decision making, an independent set of current preferences for each decision is needed. Therefore, situational preferences are stored within the LaraDecisionData objects for every single decision and are determined in the preprocessor.
NOTE: In case of only one decision there is no drawback since there exists only one LaraDecisionData object per agent.
LaraDecider objects are instantiated anew each time step for every decision since they are filled with the agent's current preferences.
LaraDeciderFactories are planned as Singletons and may be used for several DecisionBuilders.
Since method dispatching works only at compile time it is not possible to overload onEvent(event) with the particular specific event classes because at compile time it is not defined which events occur.
It is not possible to parameterise subscribers with an event type since the eventbus may not distingish subscripbers with respect to their event parameter and thus may not call onEvent() with a specific event type.
Goals need to be consistent throughout the architecture for preferences, behavioural option utilities and matrix columns. Goals are represented as Class(? extends LaraGoal) objects. In comparison to LaraGoal instances class objects are easier to check for equality (which is often required throughout Lara). For each goal there is only one class instance which requires less space and is much more save.
Various preference weights according to context etc. are not required since the pre-processor updates preference weights to the context. Because goals are contained in immutable objects they need to be immutable as well.
Tt is probable that the checking depends on the BO, and therefore the standard is the BO's checking method is called directly with environmental values and accuracy level. Of course, the BO class could depend on further agent properties and fetch these by itself. But: For this, we need to carry a reference to the agent along to the BO class..
The alternative is less adequate: The BOChecker would fetch environmental conditions once, fetch the condition table of the BO and check. Different "levels of validity" could be applied by exchanging the BOChecker. Also this way, if there are more complicated procedures to check the applicability the BOChecker could redirect the checking to a certain method of the BO (an entry in the condition table of the BO could indicate the requirement for redirection).
Parameterised agent and behavioural option classes allow the modeller to design classes that go well together, i.e. that avoid casting in many cases. Wild-card expressions for parameters allow for more flexibility since they allow agent classes to be designed for groups of behavioural options and vice verse. However, parameter expressions often may seem complicated and confusing. There is an exampe case in tests in LARA_Base (LParameterTest) which might clear things up.
The modeller is required to implement agents against the most specific, common behavioural option, and to implement BOs against their most specific, but common agent class: Therefore, a one-to-one-match between agent classes and the BOs they deal with is required. Thus, it is not possible to constrain types in "middle classes", i.e. abstract classes. Consequently, the agent parameter of the BO parameter of the BO's agent parameter (BOAgent<Agent,BO<Agent>>) must be the agent parameter itself.
However, it could have been advantageous to use a BO class as BO's agent parameter's BO parameter that is parameterised with the agent's super class as parameter and thus use the BO more flexibly while allowing specific code for the agent class within the BO class. Instead, BO's need to be designed for more general agent classes. To make it work, the agent's BO's agent parameter need to be independent from the agents's.
LaraAgentAgentT, ? extends LaraBehaviouralOption<? super AgentT> is not feasible, since it requires the parameter of the agent's BO parameter to be a super type of AgentT whereas the (actual) BO requires its AgentT to extend LaraAgent. Therefore, AgentT should extend LaraAgent and should be a super type of an extension of LaraAgent. We thus skip wild-cards for agent's parameter on agent's BOs and for BO parameter for BO's agent. ===
BO extends LaraBehaviouralOption? super A, BO as BO parameter for BOs does not make sense since the the agent parameter A characterises just the focal BO, and the BO's BO parameter should not deviate from that agent class A. The BO requires a BO parameter to define the return type of getModifiedBo(...)
Problematic is to define BOs that constrain agents by a certain class, and that agent class that constrains the same BOs simultaneously. Omit BO parameter of BO's? May clear things up. Disadvantage: BOs need to implement more getModified(x)-methods.