.. highlight:: yaml .. index:: links .. _links_label: Links ===== Entities can be linked with each other or with other entities, for example, individuals belong to households, and mothers are linked to their children, while partners are interlinked as well. A typical link has the following form: :: name: {type: , target: , field: } LIAM 2 uses integer fields to establish the link between entities. Those integer fields contain the id-number of the linked individual. LIAM 2 allows two types of links: many2one and one2many. .. index:: many2one many2one -------- A **many2one** link the item of the entity to *one* other item in the same (eg. a person to its mother) or another entity (eg. a person to its household). This allows the modeller to use information stored in the linked entities. :: entities: person: fields: - age: int - income: float - mother_id: int - father_id: int - partner_id: int links: mother: {type: many2one, target: person, field: mother_id} father: {type: many2one, target: person, field: father_id} partner: {type: many2one, target: person, field: partner_id} processes: age: age + 1 mother_age: mother.age parents_income: mother.income + father.income To access a field of a linked individual (possibly of the same entity), you use: :: link_name.field_name For example, the *mother_age* process uses the 'mother' link to assign the age of the mother to the *mother_age* field. If an individual's link does not point to anything (eg. a person has no known mother), trying to use the link would yield the missing value (eg. for orphans, mother.age is -1 and parents_income is *nan*). As another example, the process below sets a variable *to_separate* to *True* if the variable *separate* is True for either the individual or his/her partner. :: - to_separate: separate or partner.separate Note that it is perfectly valid to chain links as, for example, in: :: grand_parents_income: mother.mother.income + mother.father.income + father.mother.income + father.father.income Another option to get values in the linked individual is to use the form: :: link_name.get(expr) this syntax is a bit more verbose in the simple case, but is much more powerful as it allows to evaluate (almost) any expression on the linked individual. For example, if you want to get the average age of both parents of the mother of each individual, you can do it so: mother.get((mother.age + father.age) / 2) .. index:: one2many one2many -------- A **one2many** links an item in an entity to at least one other item in the same (eg. a person to its children) or other entity (a household to its members). :: entities: household: links: persons: {type: one2many, target: person, field: household_id} person: fields: - age: int - income: float - household_id : int links: household: {type: many2one, target: household, field: household_id} - *persons* is the link from the household to its members. - *household* is the link form a person to the household. To use information stored in the linked entities you have to use *aggregate functions* - countlink (eg. countlink(persons) gives the numbers of persons in the household) - sumlink (eg. sumlink(persons, income) sums up all incomes from the members in a household) - avglink (eg. avglink(persons, age) gives the average age of the members in a household) - minlink, maxlink (eg. minlink(persons, age) gives the age of the youngest member of the household) *example* :: entities: household: fields: - num_children: int links: # link from a household to its members persons: {type: one2many, target: person, field: household_id} processes: num_children: countlink(persons, age < 18) person: fields: - age: int - household_id: int links: # link form a person to his/her household household: {type: many2one, target: household, field: household_id} processes: num_kids_in_hh: household.num_children The num_children process, once called will compute the number of persons aged 17 or less in each household and store the result in the *num_children* field (of the **household**). Afterwards, that variable can be used like any other variable, for example through a many2one link, like in the *num_kids_in_hh* process. This process computes for each **person**, the number of children in the household of that person. Note that the variable *num_kids_in_hh* could also have been simulated by just one process, on the "person" level, by using: :: - num_kids_in_hh: household.get(countlink(persons, age < 18))