Quickly Switch between Blocks
This guide explains how multiple building blocks, serving the same purpose can be used within one Agent thus allowing to experiment and compare two approaches. We will explain the procedures along the example of the Interaction concept.
Frequently switching between building blocks is often
necessary when evaluating which model fits well for the system at hand.
cellular_raza
makes extensive use of compile-time generics for which it is important to know what
types we are dealing with.
This means that we are left with two fundamental differing options:
- Preserve performance but restrict ourselves to a predefined set of blocks
- Allow maximum Flexibility at the expense of computational overhead
Select Set of Blocks
Identical Signatures
For this example, we assume that all types for position, velocity and force are identical.
The type for exchanging interaction information may however be distinct.
This means that we can implement the
Interaction trait by using 2 generic
parameters <T, I>
and implementing Interaction<T, T, T, I>
.
|
|
|
|
We assume that that the interaction information behind the generic parameter I
has the same type
and interpretation for both interaction variants.
For example, the MiePotential
and the MorsePotential
both exchange the radius variable and are thus compatible with each other.
If one of those types would exchange the diameter instead of the radius, the implementation would
still work but the interpretation of the exchanged information would not be identical and thus wrong
results would be calculated.
Differing Information
In this section we will deal with two interaction types that have different information types
I1, I2
.
|
|
We assume here that we pick one of the two variants in the beginning and thus initialize all agents with this variant. In the case where multiple variants can be chosen simultaneously, we would have to specify the two conditions
Sketched Implementation
fn calculate_force_between(
...,
) -> Result<(T, T), CalcError> {
use SphericalInteraction::*;
match (self, ext_info) {
// See as above
... ,
// Also implement functionality here
(BLJ(pot), IInf::Morse(inf)) => ...,
(Morse(pot), IInf::BLJ(inf)) => ...,
}
}
Differing Position, Velocity, Force
We assume that the position, velocity and force types are distinct but shared between the different interaction types.
|
|
In the case where each interaction potential has its own
position, velocity or
force type, we need to also construct enums for position
enum PPos<P1, P2, ..> {..}
just as we did for the interaction information IInf<I1, I2, ..> {..}
.
Additionally, we will now have to also implement the
Xapy
trait for these types in order to
be able to numerically use them.
We do not in general recommend this approach and would advise to consider to try in using distinct
information types instead.