First, a hierarchy of entity types is set up. The system dynamics models shown earlier contain only three types of participant: variables, stocks and flows. Here, stocks and flows are a special type of variable with a predetermined meaning. That is, a flow into a stock corresponds to the equation and a flow out of a stock denotes . Hence, stocks and flows are defined as subclasses of the participant class variable:

(defEntity variable) (defEntity stock :subclass-of (variable)) (defEntity flow :subclass-of (variable))

The sample properties defined in section 3.2.3, which describe the condition under which a variable is endogenous or exogenous, are employed in this knowledge base:

(defproperty endogenous-1 :source-participants ((?v :type variable)) :structural-conditions ((== ?v *)) :property (endogenous ?v)) (defproperty endogenous-2 :source-participants ((?v :type variable)) :structural-conditions ((d/dt ?v *)) :property (endogenous ?v)) (defproperty exogenous :source-participants ((?v :type variable)) :structural-conditions ((not (endogenous ?v))) :property (exogenous ?v))

The next three model fragments contain the rules of the stock-flow diagrams employed by systems dynamics models. They respectively describe that:

- A flow
`?flow`into a stock`?stock`corresponds to the composable differential equation:

- A flow
`?flow`out of a stock`?stock`corresponds to the composable differential equation:

- A flow
`?flow`from one stock`?stock1`to another stock`?stock2`corresponds to the composable differential equations:and

(defModelFragment inflow :source-participants ((?stock :type stock) (?flow :type flow)) :structural-conditions ((flow ?flow source ?stock)) :postconditions ((d/dt ?stock (C-add ?flow))))

(defModelFragment outflow :source-participants ((?stock :type stock) (?flow :type flow)) :structural-conditions ((flow ?flow ?stock sink)) :postconditions ((d/dt ?stock (C-sub ?flow))))

(defModelFragment inflow :source-participants ((?stock1 :type stock) (?stock2 :type stock) (?flow :type flow)) :structural-conditions ((flow ?flow ?stock1 ?stock2)) :postconditions ((d/dt ?stock1 (C-sub ?flow)) (d/dt ?stock2 (C-add ?flow))))

Once the above declarations are in place, the knowledge base of model fragments can be defined. The first model fragment describes the population growth phenomenon. Note that all of the aforementioned growth, predation and competition models contain a stock representing population size and two flows, one flow of births into the stock and another flow of deaths out of the stock. This common feature of models on population dynamics is contained in a single model fragment.

(defModelFragment population-growth :source-participants ((?population :type population)) :assumptions ((relevant growth ?population)) :target-participants ((?size :type stock :name size) (?birth-flow :type flow :name births) (?death-flow :type flow :name deaths)) :postconditions ((flow ?birth-flow source ?size) (flow ?death-flow ?size sink) (size-of ?size ?population) (births-of ?birth-flow ?population) (deaths-of ?death-flow ?population)) :purpose-required ((endogenous ?birth-flow) (endogenous ?death-flow)))

The variables `?birth-flow` and `?death-flow` become
endogenous if the model contains an equation describing birth flow and
death flow. These equations differ between population growth models.
Two types of population growth model are the exponential growth model
[26], which is shown in Figure
8(a), and the logistic growth model
[43], which is shown in Figure
8(b). The following two model
fragments formally describe these component models:

(defModelFragment exponential-population-growth :source-participants ((?population :type population) (?size :type variable) (?birth-flow :type variable) (?death-flow :type variable)) :structural-conditions ((size-of ?size ?population) (births-of ?birth-flow ?population) (deaths-of ?death-flow ?population)) :assumptions ((model ?size exponential)) :target-participants ((?birth-rate :type variable :name birth-rate) (?death-rate :type variable :name death-rate)) :postconditions ((== ?birth-flow (* ?birth-rate ?size)) (== ?death-flow (* ?death-rate ?size))))

(defModelFragment logistic-population-growth :source-participants ((?population :type population) (?size :type variable) (?birth-flow :type variable) (?death-flow :type variable)) :structural-conditions ((size-of ?size ?population) (births-of ?birth-flow ?population) (deaths-of ?death-flow ?population)) :assumptions ((model ?size logistic)) :target-participants ((?birth-rate :type variable :name birth-rate) (?death-rate :type variable :name death-rate) (?density :type variable :name total-population) (?capacity :type variable :name capacity)) :postconditions ((== ?birth-flow (* ?birth-rate ?size)) (== ?death-flow (* ?death-rate ?size ?density)) (== ?density (C-add (/ ?size ?capacity))) (density-of ?density ?population) (capacity-of ?capacity ?population)))

There is one twist in compositional modelling of population growth. Sometimes, the actual growth model is implicitly contained within another type of model. In such cases, the growth phenomenon and the corresponding differential equations are still relevant, but none of the dedicated growth models can be employed. For example, as will be shown later, the Lotka-Volterra predation model comes with its own equations describing growth.

The model fragment `other-growth` allows for an empty growth
model, named `other`, to be selected. However, due to the
purpose-required property that any instance of `?p-change` must
be endogenous, this empty model can only be selected if a growth model
is implicitly included elsewhere.

(defModelFragment other-growth :source-participants ((?population :type population) (?size :type variable) (?birth-flow :type variable) (?death-flow :type variable)) :structural-conditions ((size-of ?size ?population) (births-of ?birth-flow ?population) (deaths-of ?death-flow ?population)) :assumptions ((model ?population other)))

In addition to population growth, two other phenomena are included in
the knowledge base: predation and competition. Predation and
competition relations between species are represented by predicates
over the populations: e.g. `(predation foxes rabbits)`
and `(competition sheep cows)`. However the
existence of a phenomenon does not necessarily mean that it must be
contained within the model. It would make little sense to model
predation and competition without modelling the size of the
populations, because models of these phenomena relate population sizes
to one another. Therefore, the incorporation of the predation
phenomenon is made dependent upon the existence of variables
representing population size. Also, human expert modellers may prefer
to leave a phenomenon out of the resulting model. To keep this choice
open, the following two model fragments construct a participant
representing the phenomena of predation and competition, and make it
dependent upon a relevance assumption:

(defModelFragment predation-phenomenon :source-participants ((?predator :type population) (?prey :type population) (?predator-size :type variable) (?prey-size :type variable)) :structural-conditions ((predation ?predator ?prey) (size-of ?predator-size ?predator) (size-of ?prey-size ?prey)) :assumptions ((relevant predation ?predator ?prey)) :target-participant ((?predation-phenomenon :type phenomenon :name predation-phenomenon)) :postconditions ((predation-phenomenon ?predation-phenomenon ?predator ?prey)) :purpose-required ((has-model ?predation-phenomenon)))

(defModelFragment competition-phenomenon :source-participants ((?population1 :type population) (?population2 :type population) (?size1 :type variable) (?size2 :type variable)) :structural-conditions ((competition ?population1 ?population2) (size-of ?size1 ?population1) (size-of ?size2 ?population2)) :assumptions ((relevant competition ?population1 ?population2)) :target-participant ((?competition-phenomenon :type phenomenon :name competition-phenomenon)) :postconditions ((competition-phenomenon ?competition-phenomenon ?population1 ?population2)) :purpose-required ((has-model ?competition-phenomenon)))

Both model fragments have a purpose-required property of the form
`(has-model ?phen)`. This property expresses the condition
that a model must exist with respect to a phenomenon:

(defproperty has-model :source-participants ((?p :type phenomenon)) :structural-conditions ((is-model-of ?p *)) :property (has-model ?p))

The next two model fragments implement such models (thereby satisfying
the above `has-model` purpose-required property) for the
predation phenomenon between two populations. They describe two
well-known predation models: the Lotka-Volterra model
[25,44], which is shown in Figure
9(a), and the Holling model
[16], which is shown graphically in Figure
9(b).

(defModelFragment Lotka-Volterra :source-participants ((?predation-phenomenon :type phenomenon) (?predator :type population) (?predator-size :type stock) (?predator-birth-flow :type flow) (?predator-death-flow :type flow) (?prey :type population) (?prey-size :type stock) (?prey-birth-flow :type flow) (?prey-death-flow :type flow)) :structural-conditions ((predation-phenomenon ?predation-phenomenon ?predator ?prey) (size-of ?predator-size ?predator) (births-of ?predator-birth-flow ?predator) (deaths-of ?predator-death-flow ?predator) (size-of ?prey-size ?prey) (births-of ?prey-birth-flow ?prey) (deaths-of ?prey-death-flow ?prey)) :assumptions ((model ?predation-phenomenon lotka-volterra)) :target-participants ((?prey-birth-rate :type variable :name birth-rate) (?predator-factor :type variable :name predator-factor) (?prey-factor :type variable :name prey-factor) (?predator-death-rate :type variable :name death-rate)) :postconditions ((== ?prey-birth-flow (* ?prey-birth-rate ?prey-size)) (== ?predator-birth-flow (* ?predator-factor ?prey-size ?predator-size)) (== ?prey-death-flow (* ?prey-factor ?prey-size ?predator-size)) (== ?predator-death-flow (* ?predator-death-rate ?predator-size)) (is-model-of lotka-volterra ?predation-phenomenon)))

As mentioned earlier, the Lotka-Volterra model introduces its own
growth model for the prey and predator populations by assigning
specific equations to the variables, which describe changes in the
sizes of the predator and prey populations, `?pred-change` and
`?prey-change` respectively. Thus, it satisfies the
purpose-required property in the application of the
`population-growth` model fragment for the `?prey` and
`?pred` populations.

(defModelFragment Holling :source-participants ((?predation-phenomenon :type phenomenon) (?predator :type population) (?predator-size :type stock) (?capacity :type variable) (?prey :type population) (?prey-size :type stock)) :structural-conditions ((predation-phenomenon ?predation-phenomenon ?predator ?prey) (size-of ?predator-size ?predator) (size-of ?prey-size ?prey) (capacity-of ?capacity ?predator)) :assumptions ((model ?predation-phenomenon holling)) :target-participants ((?search-rate :type variable :name search-rate) (?handling-time :type variable :name handling-time) (?prey-requirement :type variable :name prey-requirement) (?predation :type flow :name predation)) :postconditions ((flow ?predation ?prey-size sink) (== ?predation (/ (* ?search-rate ?prey-size ?predator-size) (+ 1 (* ?search-rate ?prey-size ?handling-time)))) (== ?capacity (C-add (* ?prey-requirement ?prey))) (is-model-of holling ?predation-phenomenon)))

The Holling model employs a variable denoting the capacity of a population. Such a variable may be introduced by a logistic growth model. In practice, logistic growth models and Holling predation models are often used in conjunction. The compositional modeller need not be aware of such combinations of models, however. All it needs to know is the prerequisites of the individual component models contained within each model fragment.

The final model fragment in the knowledge base implements a model of competition between two species. It formally describes the competition model type depicted in Figure 10. As this model fragment contains the only population competition model in the knowledge base, it does not contain a model assumption to represent the model.

(defModelFragment competition :source-participants ((?competition-phenomenon :type phenomenon) (?population-1 :type population) (?size-1 :type stock) (?density-1 :type variable) (?capacity-1 :type variable) (?population-2 :type population) (?size-2 :type stock) (?density-2 :type variable) (?capacity-2 :type variable)) :structural-conditions ((competition-phenomenon ?competition-phenomenon ?population-1 ?population-2) (density-of ?density-1 ?size-1) (capacity-of ?capacity-1 ?size-1) (density-of ?density-2 ?size-2) (capacity-of ?capacity-2 ?size-2)) :assumptions ((relevant competition ?population-1 ?population-2)) :target-participants ((?weight-12 :type variable :name weight) (?weight-21 :type variable :name weight)) :postconditions ((== ?density-1 (C-add (/ (* ?weight-12 ?size-2) ?capacity-1))) (== ?density-2 (C-add (/ (* ?weight-21 ?size-1) ?capacity-2)))))