Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Gerwitz <mike.gerwitz@rtspecialty.com>2018-01-04 16:08:42 -0500
committerMike Gerwitz <mike.gerwitz@rtspecialty.com>2018-09-11 09:30:51 -0400
commitf4b42136d05581b16255f89235f363dc728f6376 (patch)
tree30a3d231c2abf5e6e11cf517b0c5f8d32be7bae5
parent5267baa0e9d8544280a0721f6240fac8afa0f0af (diff)
downloadtame-f4b42136d05581b16255f89235f363dc728f6376.tar.gz
tame-f4b42136d05581b16255f89235f363dc728f6376.tar.bz2
tame-f4b42136d05581b16255f89235f363dc728f6376.zip
Add aggregate package
* aggregate.xml: Add package. * test/core/aggregate.xml: Add test case. * test/core/suite.xml: Import new aggregate package.
-rw-r--r--core/aggregate.xml154
-rw-r--r--core/test/core/aggregate.xml264
-rw-r--r--core/test/core/suite.xml1
3 files changed, 419 insertions, 0 deletions
diff --git a/core/aggregate.xml b/core/aggregate.xml
new file mode 100644
index 0000000..0bd33c2
--- /dev/null
+++ b/core/aggregate.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2018 R-T Specialty, LLC.
+
+ This file is part of tame-core.
+
+ tame-core is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<package xmlns="http://www.lovullo.com/rater"
+ xmlns:c="http://www.lovullo.com/calc"
+ xmlns:t="http://www.lovullo.com/rater/apply-template"
+ core="true"
+ desc="Aggregating Values">
+
+ <import package="base" export="true" />
+ <import package="vector/cmatch" export="true" />
+
+
+ Aggregate templates simplify aggregating values through various means.
+ Unless otherwise specified,
+ the default means of aggregation is summation.
+
+
+ <section title="Symbol-Based Aggregation">
+ For large numbers of values,
+ the most convenient way to aggregate is by matching on symbol names.
+ Note that symbols must be available for a match to occur.
+ All imported symbols are immediately available,
+ but \tt{expand-sequence} may need to be used for symbols produced by
+ the same package.
+
+
+ \ref{_aggregate-rate-each_} aggregates values of generators (usually
+ referred to by \tt{rate-each}) through summation.
+ A \tt{rate-each} block is generated to perform the summation.
+
+ Since \tt{rate-each} multiplies its body by \tt{_CMATCH_},
+ zero symbols would normally result in the summation of \tt{_CMATCH_}
+ itself, which is not desirable;
+ this template always includes \ref{ZERO} in the body to defend
+ against this,
+ causing a yield of~$0.00$ if there are no symbol matches.
+
+ <template name="_aggregate-rate-each_"
+ desc="Aggregate generator values by symbol prefix">
+ <param name="@class@" desc="Iterator class (omit for scalars)" />
+ <param name="@prefix@" desc="Symbol prefix" />
+
+ <param name="@yields@" desc="Scalar yield name (optional)">
+ <text></text>
+ </param>
+
+ <param name="@generates@" desc="Generator name (optional)">
+ <text></text>
+ </param>
+
+
+ <rate-each class="@class@" yields="@yields@"
+ generates="@generates@" index="k">
+ <c:sum>
+ <!-- prevent summing _CMATCH_ if there are no symbols (see above
+ comments) -->
+ <c:value-of name="ZERO"
+ label="Guard against zero symbol matches" />
+
+ <inline-template>
+ <for-each>
+ <sym-set name-prefix="@prefix@" type="gen" />
+ </for-each>
+
+ <c:value-of name="@sym_name@" index="k" />
+ </inline-template>
+ </c:sum>
+ </rate-each>
+ </template>
+
+
+ \ref{_aggregate-rate_} is analgous to \ref{_aggregate-rate-each_},
+ handling only scalar~\tt{@yields@}.
+ A \tt{rate} block is generated to aggregate by summation.
+
+ To prevent an empty rate block from being generated if there are no
+ symbol matches,
+ \ref{ZERO} is always included as part of the summation.
+
+ <template name="_aggregate-rate_"
+ desc="Aggregate scalar results by symbol prefix">
+ <param name="@prefix@" desc="Symbol prefix" />
+ <param name="@yields@" desc="Scalar yield name" />
+
+
+ <rate yields="@yields@">
+ <c:sum>
+ <!-- prevent completely empty rate block -->
+ <c:value-of name="ZERO"
+ label="Guard against zero symbol matches" />
+
+ <inline-template>
+ <for-each>
+ <sym-set name-prefix="@prefix@" type="rate" />
+ </for-each>
+
+ <c:value-of name="@sym_name@" />
+ </inline-template>
+ </c:sum>
+ </rate>
+ </template>
+
+
+ \ref{_aggregate-classify_} aggregates classifications.
+ Keep in mind that classifications act as universal quantifiers by default,
+ meaning zero symbol matches will produce a match and a scalar~$1$;
+ existential quantifiers (\tt{@any@} set to \tt{true}) will \emph{not}
+ match and will produce the scalar~$0$.
+
+ <template name="_aggregate-classify_"
+ desc="Aggregate classification results by symbol prefix">
+ <param name="@prefix@" desc="Symbol prefix" />
+ <param name="@as@" desc="Classification name" />
+ <param name="@desc@" desc="Generated classification description" />
+
+ <param name="@yields@" desc="Vector yield name (optional)">
+ <text></text>
+ </param>
+
+ <param name="@any@"
+ desc="Existential classification (default false, universal)">
+ <text></text>
+ </param>
+
+
+ <classify as="@as@" yields="@yields@" desc="@desc@" any="@any@">
+ <inline-template>
+ <for-each>
+ <sym-set name-prefix="@prefix@" type="class" />
+ </for-each>
+
+ <t:match-class name="@sym_name@" />
+ </inline-template>
+ </classify>
+ </template>
+ </section>
+</package>
diff --git a/core/test/core/aggregate.xml b/core/test/core/aggregate.xml
new file mode 100644
index 0000000..ecfac52
--- /dev/null
+++ b/core/test/core/aggregate.xml
@@ -0,0 +1,264 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2018 R-T Specialty, LLC.
+
+ This file is part of tame-core.
+
+ tame-core is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<package xmlns="http://www.lovullo.com/rater"
+ xmlns:c="http://www.lovullo.com/calc"
+ xmlns:t="http://www.lovullo.com/rater/apply-template"
+ desc="Aggregate Package Specification">
+
+ <import package="../../base" />
+ <import package="../../test/spec" />
+
+ <import package="../../base" />
+ <import package="../../vector/cmatch" />
+ <import package="../../vector/stub" />
+
+ <import package="../../aggregate" />
+
+
+ <rate-each class="nclass3"
+ generates="aggregateGen1" index="k">
+ <c:const value="1" desc="Constant value" />
+ </rate-each>
+
+ <rate-each class="nclass3"
+ generates="aggregateGen2" index="k">
+ <c:value-of name="k" />
+ </rate-each>
+
+
+ <rate yields="aggregateRate1">
+ <c:const value="1" desc="Constant value" />
+ </rate>
+
+ <rate yields="aggregateRate2">
+ <c:const value="3" desc="Constant value" />
+ </rate>
+
+
+ <classify as="agg-class-1"
+ desc="Aggregate test 1">
+ <match on="AGG_1VEC" />
+ </classify>
+
+ <classify as="agg-class-2"
+ desc="Aggregate test 2">
+ <t:match-gt on="AGG_INCVEC" const="0" />
+ </classify>
+
+
+ <t:n-vector n="3" name="AGG_1VEC" value="1" />
+
+ <const name="AGG_INCVEC" desc="Incrementing vector">
+ <item value="0" />
+ <item value="1" />
+ <item value="2" />
+ </const>
+
+
+
+ <t:describe name="aggregate template">
+ <t:describe name="_aggregate-rate-each_">
+ <t:aggregate-rate-each class="nclass3" yields="yieldAggReEmpty"
+ prefix="doesNotExist"
+ generates="genAggReEmpty" />
+
+ <t:aggregate-rate-each class="nclass3" yields="yieldAggReNonEmpty"
+ prefix="aggregateGen"
+ generates="genAggReNonEmpty" />
+
+
+ <t:describe name="with no symbols">
+ <t:it desc="produces 0">
+ <t:given>
+ <c:sum>
+ <c:value-of name="yieldAggReEmpty" />
+ <c:sum of="genAggReEmpty" />
+ </c:sum>
+ </t:given>
+
+ <t:expect>
+ <t:match-result eq="0" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+
+
+ <t:describe name="with symbols">
+ <t:it desc="sums respective index of each symbol">
+ <t:given>
+ <c:sum of="genAggReNonEmpty" />
+ </t:given>
+
+ <t:expect>
+ <!-- 1 + 2 + 3 -->
+ <t:match-result eq="6" />
+ </t:expect>
+ </t:it>
+
+
+ <t:it desc="yields sum of symbols">
+ <t:given>
+ <c:value-of name="yieldAggReNonEmpty" />
+ </t:given>
+
+ <t:expect>
+ <!-- same as above -->
+ <t:match-result eq="6" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+ </t:describe>
+
+
+ <t:describe name="_aggregate-rate_">
+ <t:aggregate-rate prefix="doesNotExist" yields="yieldAggRateEmpty" />
+ <t:aggregate-rate prefix="aggregateRate" yields="yieldAggRateNonEmpty" />
+
+ <t:describe name="with no symbols">
+ <t:it desc="yields 0">
+ <t:given>
+ <c:value-of name="yieldAggRateEmpty" />
+ </t:given>
+
+ <t:expect>
+ <t:match-result eq="0" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+
+
+ <t:describe name="with symbols">
+ <t:it desc="yields sum of symbols">
+ <t:given>
+ <c:value-of name="yieldAggRateNonEmpty" />
+ </t:given>
+
+ <t:expect>
+ <t:match-result eq="4" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+ </t:describe>
+
+
+ <t:describe name="_aggregate-classify_">
+ <t:describe name="as a univiersal quantifier">
+ <t:aggregate-classify prefix="does-not-exist" as="class-agg-univ-empty"
+ desc="Aggregate universal class empty test"
+ yields="classAggUnivEmpty" />
+ <t:aggregate-classify prefix="agg-class-" as="class-agg-univ-nonempty"
+ desc="Aggregate class nonempty test"
+ yields="classAggUnivNonEmpty" />
+
+ <t:describe name="with no symbols">
+ <t:it desc="produces scalar 1">
+ <t:given>
+ <c:value-of name="classAggUnivEmpty" />
+ </t:given>
+
+ <t:expect>
+ <t:match-result eq="1" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+
+
+ <t:describe name="with symbols">
+ <t:it desc="generates matching class">
+ <rate-each class="class-agg-univ-nonempty"
+ yields="aggUnivNonEmptyCheck"
+ index="k">
+ <c:const value="1" desc="Truth check" />
+ </rate-each>
+
+ <t:expect>
+ <!-- two non-zero in AGG_INCVEC -->
+ <t:match-eq on="aggUnivNonEmptyCheck" const="2" />
+ </t:expect>
+ </t:it>
+
+
+ <t:it desc="produces vector">
+ <t:given>
+ <c:sum of="classAggUnivNonEmpty" />
+ </t:given>
+
+ <t:expect>
+ <!-- two non-zero in AGG_INCVEC -->
+ <t:match-result eq="2" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+ </t:describe>
+
+
+ <t:describe name="as a existential quantifier">
+ <t:aggregate-classify prefix="does-not-exist" as="class-agg-exist-empty"
+ desc="Aggregate existersal class empty test"
+ yields="classAggExistEmpty"
+ any="true" />
+ <t:aggregate-classify prefix="agg-class-" as="class-agg-exist-nonempty"
+ desc="Aggregate class nonempty test"
+ yields="classAggExistNonEmpty"
+ any="true" />
+
+ <t:describe name="with no symbols">
+ <t:it desc="produces scalar 0">
+ <t:given>
+ <c:value-of name="classAggExistEmpty" />
+ </t:given>
+
+ <t:expect>
+ <t:match-result eq="0" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+
+
+ <t:describe name="with symbols">
+ <t:it desc="generates matching class">
+ <rate-each class="class-agg-exist-nonempty"
+ yields="aggExistNonEmptyCheck"
+ index="k">
+ <c:const value="1" desc="Truth check" />
+ </rate-each>
+
+ <t:expect>
+ <!-- all match in AGG_1VEC -->
+ <t:match-eq on="aggExistNonEmptyCheck" const="3" />
+ </t:expect>
+ </t:it>
+
+
+ <t:it desc="produces vector">
+ <t:given>
+ <c:sum of="classAggExistNonEmpty" />
+ </t:given>
+
+ <t:expect>
+ <!-- all match in AGG_1VEC -->
+ <t:match-result eq="3" />
+ </t:expect>
+ </t:it>
+ </t:describe>
+ </t:describe>
+ </t:describe>
+ </t:describe>
+</package>
diff --git a/core/test/core/suite.xml b/core/test/core/suite.xml
index c3c4505..e29e839 100644
--- a/core/test/core/suite.xml
+++ b/core/test/core/suite.xml
@@ -33,6 +33,7 @@
<import package="vector/length" />
<import package="vector/stub" />
+ <import package="aggregate" />
<import package="insurance" />
<import package="tplgen" />