The An’d’rea Framework – Design Notes
This is the follow up to my previous post on the An’d’rea Framework. These are some random notes and are not particularly as well organised as I would hope them to be, but would probably serve as great reference for posterity.
GSE Notes :
- The generic simulation engine is a discrete-event timestep simulation engine.
- At any point in time there is only one environment in the GSE.
- Each GSE can have as many agents as required (maintained internally by an AgentList)
- Each GSE has atmost one state object.
- The most fundamental event in the GSE is the Step event, indicating a timestep. All SimObj’s respond to the step event (pre, sim, post). The step event is applied to the Environment after it has been applied to all Agents.
SimObj Notes :
This is an abstract base class for all simulatable objects and all simulatable objects respond to the following messages.
The GetProperty and SetProperty functions work on a hash table indexed by string keys, and contain closures, which can be evaluated to get the value (GetPropertyValue), or get the closure itself (GetProperty).
The use of closures here is done for 3 main reasons.
- It avoids using a circuitious reflection mechanism and hence the Metrics classes can directly querry the hashtable about the nature of the property.
- Property values can be calculated dynamically.
- Sometimes, Property Values need to be calculated from external C code, and hence closures form thin wrappers around the C code.
Apart from the above given reasons, closures are natural for certain activities that are described below.
Use of Closures :
The entire architecture is based on using closures as an essantial communication mechanism, as it allows the engine to create a dynamical schedule (which is necessary). Since most messages schedule events in the future, the message can send closures to the Engine, which the engine can execute at the specified future time.
Regards to implementing properties as hash-table of closures, that means that the code can install a different closure if required on the fly. And why is this important, Because of this stated goal of the system .
Having installable behaviour in runtime code means that, essentailly more intelligence can be incorporated into the system by having more than one behaviour at hand, and using an appropriate one as the situtation demands. Also, in case of efficiency comparisons, two seperate tests need not be carried out, as the code can install both the behaviours dynamically and compare them at runtime. Also, testing and simulating various algorithms with minor variations is only a matter of modifying some of the behaviours (i.e, installing different closures for common properties).
Take this example of an adaptive system, simulating a group of creatures on an event horizon in the system (Filthy stock borkers, who have come to know of a huge stock market scandal). Now adaptive creatures will have to exhibit radically different behaviour at runtime, so how do you incorporate the fact in the progmatically easiest way possible? Simple – install a new closure for the old behaviour.