tame/core/vector/matrix.xml

96 lines
4.1 KiB
XML

<?xml-stylesheet type="text/xsl" href="summary.xsl"?>
<lv:package
xmlns:lv="http://www.lovullo.com/rater"
xmlns:c="http://www.lovullo.com/calc"
xmlns:t="http://www.lovullo.com/rater/apply-template"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.lovullo.com/rater ../../rater.xsd"
core="true"
name="core/vector/matrix"
desc="Matrix (vector of vectors) arithmetic">
<lv:import package="../base" />
<lv:import package="list" />
<!--
Extracts a vector of rates (a value for each location) associated with the
requested class and line codes
This seems more complicated/confusing than it really is, so it helps to
look at an example. Consider that we have the following data passed to this
template (assuming that this is the data that will exist at runtime):
R = [ [ "A", "B" ], [ "C" ], [ "D", "E" ] ]
C = [ [ 1 , 0 ], [ 0 ], [ 0, 1 ] ]
L = "gl"
Given matrix R (@rate_matrix@) and the classification matches C, for any
index that matches the given line L, a dot product will be performed. Let
us assume that indexes 0 and 2 match GL; we would then have the following
dot product:
R = [ [ "A", "B" ], ..., [ "D", "E" ] ]
C = [ [ 1 , 0 ], ..., [ 0, 1 ] ]
= [ "A", "E" ]
And so the resulting vector would be [ "A", "E" ]. To put this into an
example within the context of dwelling, let C above be the classification
set for all vacant buildings. Then, [ "A", "E" ] would be the rate
associated with the vacant building class code for locations 0 and 2
respectively.
If multiple matches are found per location, then the two rates will be
summed (as that is how dot products work), which is obviously not good.
However, this should not be a problem, because you should not have
duplicate class codes per location. Fix your data if that happens.
(Note that the dot product is actually performed for each index and then
multiplied by the classification match __CMATCH__, so while the effect
above is true, the result is achieved in a slightly different manner.)
-->
<!-- TODO: more generic name and documentation; we are in the core, after all -->
<lv:template name="_rate-vector_" desc="Matches against a matrix of classes and a matrix of rates and returns a vector representing the rates per location">
<lv:param name="@line@" desc="Line code classification string" />
<lv:param name="@class_set@" desc="Matrix containing line classification matches" />
<lv:param name="@into@" desc="Variable to which the vector will be assigned" />
<!-- this would be the sum of all the rates, which really is useless, but the XML requires it -->
<lv:param name="@yields@" desc="Variable to yield to (useless, but required)">
<lv:text>__</lv:text>
<lv:param-value name="@into@" />
</lv:param>
<lv:param name="@rate_matrix@" desc="Matrix containing the rates for the given line">
<lv:text>rate_</lv:text>
<lv:param-value name="@line@" />
</lv:param>
<lv:rate-each class="@line@" accumulate="none" yields="@yields@" generates="@into@" index="k">
<!-- take the dot product of the two vectors (each part of a larger matrix)
to get the rate for the associated class code -->
<c:product dot="true" label="Dot product between the class and rate vectors for each location will yield the respective rate per location">
<c:value-of name="@class_set@" index="k" />
<c:value-of name="@rate_matrix@" index="k" />
</c:product>
</lv:rate-each>
</lv:template>
<lv:function name="mcol" desc="Retrieve a matrix column as a vector">
<lv:param name="matrix" type="float" set="matrix" desc="Matrix" />
<lv:param name="col" type="integer" desc="Column index (0-indexed)" />
<!-- generate a vector containing only the requested column from each row -->
<t:cons-until-empty set="matrix" car="row">
<c:value-of name="row">
<c:index>
<c:value-of name="col" />
</c:index>
</c:value-of>
</t:cons-until-empty>
</lv:function>
</lv:package>