In many practical situations, it is desirable to use different subscript families to mean the same thing. If no special preparation is made, this leads to an error message (typically that a Subscript Range appears on the right, but not on the left, of an equation). Mapping allows you to do this sort of thing when you are very sure that you want to override the exact correspondences normally enforced. Mapping is usually safer than using the VECTOR ELM MAP function because changes you might make to Subscripts that would invalidate an equation are more likely to trigger error messages.
It is worth noting that the function VECTOR SELECT can also be used to accomplish many of the same things as mapping can.
Quite simply a mapping is an indication to Vensim that a Subscript that appears on the right but not the left of an equation has a valid interpretation. Normally, an equation such as
Quality[product] = work quality[worker type]
would generate an error. If, however each product is made by a single worker type then the equation does have a sensible interpretation. To signal this to Vensim we would use a Subscript Mapping as in:
worker type : wtclay, wtplastic, wtwood -> product
where
product : clay,plastic,wood
In this case the equation for Quality would not cause an error and the quality of the clay product would be the work quality of wtclay and so on. This mapping works because both the order and number of subscripts match up. In practice, this is often the case, but the more general mapping formulation is:
Rhsub:rh1,rh2->(Lhsub:lh1,lh2), (Lhbigger:Lhbsubr1,Lhbsubr2), (lhopposite:lho2,lho1)
Where
Lhsub : lh1,lh2,
Lhbigger : lhb1,lhb2,lhb3,lhb4
Lhsubr1 : lhb1,lhb3
Lhsubr2 : lhb2,lhb4
Lhopposite: lho1,lho2
In this we use commas to delimit the lists of map-to choices. There is no limit on the number of map-to choices, but it is most common to just have one or two. The map-to choices consist of the name of the map-to subscript range, followed by a colon : and the elements or subranges in the order the mapping should occur. The number of elements or subranges must match the number of elements in the definition for the subscripts.
Example 1
Suppose your model includes both personnel and manufacturing. For clarity, personnel are broken down by skill type, and manufacturing is broken down by product. If there is a one-to-one correspondence between skill sets and products, you could use:
MFG SKILLS : MACHINERS, ASSEMBLERS -> PRODUCTS
~ | index |
~ | Skill categories specific to manufacturing. |
|
PRODUCTS : PARTS, SYSTEMS
~ | index |
~ | Different phases of manufacturing. |
|
WORK FLOW[PRODUCTS] = WORK FORCE[MFG SKILLS] *
PRODUCTIVITY[MFG SKILLS]
~ | Part/year |
~ | Rate of progress in manufacture phases. |
|
The mapping symbol ( -> in the statement for MFG SKILLS in the above example) shows that you are mapping the subscripts of the range MFG SKILLS onto the subscripts of the range PRODUCTS. In other words, MACHINERS map to PARTS and ASSEMBLERS map to SYSTEMS. Obviously the number of subscripts must match (here, two in each subscript range).
The mapping symbol -> simply makes it legal for MFG SKILLS to appear on the right side of an equation whose left side uses PRODUCTS. This means that it is not necessary to write two separate equations for PARTS and SYSTEMS, as in:
WORK FLOW[PARTS] = WORK FORCE[MACHINERS] |
* PRODUCTIVITY[MACHINERS] ~~| |
WORK FLOW[SYSTEMS] = WORK FORCE[ASSEMBLERS] |
* PRODUCTIVITY[ASSEMBLERS] |
~ | Part / year |
~ | Rate of progress in manufacture phases. |
|
Multiple equations that occur when equations are duplicated only to indicate subscript mappings can be an annoying source of boring work and hard-to-find errors.
When the subscripts have many values, subscript mapping becomes almost indispensable, as in the following example:
Example 2
AGE : INFANT, CHILD, TEEN, MIDDLE, OLD
~ | index |
~ | Age cohorts of a population |
|
ALL BUT YOUNGEST : CHILD, TEEN, MIDDLE, OLD
~ | index |
~ | Age cohorts except infant |
|
PREVIOUS COHORT : INFANT, CHILD, TEEN, MIDDLE |
-> ALL BUT YOUNGEST |
~ | index |
~ | Age cohorts preceding each member of |
ALL BUT YOUNGEST |
|
POPULATION[INFANT]= INTEG ( births- aging[INFANTS], |
INITIAL POPULATION[INFANT]) ~~| |
POPULATION[ALL BUT YOUNGEST] = INTEG ( |
aging[PREVIOUS COHORT] |
- aging[ALL BUT YOUNGEST] , INITIAL POPULATION[ALL BUT YOUNGEST] ) |
~ | People |
~ | Age cohorts of a population |
|
See the model age.mdl in the directory \models\sample\other for the complete example, and see the model tubs.mdl in the same directory for another example.
Thanks to the mapping of PREVIOUS COHORT onto ALL BUT YOUNGEST, we need only two equations for POPULATION.Further, if we were to use 70 age groups instead of 5, we would still require only two equations. Without mapping, we would require as many equations for POPULATION as there were age groups.
Sometimes a set of Subscript Elements maps onto itself. For example, in a project-management model, any of several tasks can be a prerequisite of each task. Vensim offers a convenient notation for making a second copy of a subscript range, using the notation <->. This is frequently useful when you want to use a particular subscript twice in the same variable.
As an example, consider a work accomplishment structure for which prerequisite quality depends on prerequisite tasks.
Example 3
TASKS : CLEAR,DIG,BUILD
~ | index |
~ | The tasks for completion of the project. |
|
PTASKS <-> TASKS
~ | index |
~ | The prerequisite tasks for other tasks. |
|
These equations make PTASKS a full Subrange of TASKS.The second equation above is the same as the equation:
PTASKS : CLEAR,DIG,BUILD -> TASKS
~ | index |
~ | The prerequisite tasks for other tasks. |
|
You can use ptask to define, for example, prerequisite quality as:
prereq qual[task,ptask] = quality factors[ptask]
~ | dimensionless [0,1] |
~ | Prerequisite quality. |
|
This will work even though quality factors is actually defined by task, not by ptask. Composite quality can then be defined as defined as:
quality[task] = PROD( prereq qual[task,ptask!] )
~ | dimensionless |
~ | composite quality taken as the scalar product |
of prerequisite quality factors
|
The above conventions allow great economy in equation writing where two dimensional matrix sums or products are needed.
The above examples deal with direct mappings, where the number and order of subscripts match exactly. There is a more general mapping that allows greater flexibility in equation writing. For example, suppose that you are modeling a project in which there are 100 deliverables and 2 subcontractors. Each deliverable is handled by a single subcontractor. We might write the following equation to determine quality:
Example 4
quality[del] = norm qual[del] * |
eff qual fatigue[subcon] |
~ dmnl ~ The quality of the deliverable.
|
del : (DEL1-DEL100) |
~~All deliverables.|
subcon : subcon1,subcon2 -> (del:del con1,del con2)
~~ Subcontractors|
del con1 : (DEL1-DEL50)
~~ Deliverables that are the responsibility of subcontractor 1.
|
del con2 : (DEL51-DEL100)
~~ Deliverables that are the responsibility of subcontractor 2.
|
In this case, a single equation for quality replaces what could potentially become many such equations. The mapping symbol specifies not only a Subscript Range, but the particular Subranges that the mapping should be made to (del:del con1,del con2). The number of Subscript Ranges or Constants in the list must match the number in the defining equation (both 2 in this case). Also, the Subscript Ranges (and possibly Subscript Elements) making up the mapping must not overlap and must completely exhaust the second group.
Example 5
Consider two classes of metal products for both us and a competitor where each of us has one product in each class. In this case there are 4 products, but 2 classes. Still it will be convenient to use class attributes when computing some things for the metals.
class1 metal: ourC1, theirC1
class2 metal: ourC2, theirC2
our metal: ourC1,ourC2
metal: class1 metal,class2 metal
class: class1,class2->(metal:class1 metal,class2 metal),(our metal:ourC1,ourC2)
attractiveness[metal] = class attractivness[class] * effect of price attractivness[metal]
margin[our metal] = our class margin[class]
Here the use of mapping makes it easy to pass between a class and a particular product. Note that while metal has 4 elements class only has two. The mapping of class to metal determines which class to use for each metal. In this case two elements of metal belong to each element of class, but it could also have been 3 and 1.