ソースを参照

Implements some sane Value objects for dealing with observed arrays in incoming data

Caleb Fangmeier 8 年 前
コミット
b6faa30f15
共有4 個のファイルを変更した188 個の追加123 個の削除を含む
  1. 2 2
      container.hpp
  2. 12 4
      dataset.hpp
  3. 20 73
      filter.hpp
  4. 154 44
      value.hpp

+ 2 - 2
container.hpp

@@ -9,14 +9,14 @@ class GenContainer{
     private:
         std::string name;
         std::string desc;
-        std::vector<Filter*> filters;
+        std::vector<GenFilter*> filters;
     protected:
         virtual void _fill() = 0;
     public:
         GenContainer(const std::string name)
           :name(name){ }
         void add_filter(GenValue* filter){
-            filters.push_back(dynamic_cast<Filter*>(filter));
+            filters.push_back(dynamic_cast<GenFilter*>(filter));
         }
         void fill(){
             for (auto filter : filters){

+ 12 - 4
dataset.hpp

@@ -12,24 +12,32 @@ class DataSet{
     public:
         void process(){
             while( load_next() ){
-                for(auto val : values)
-                    val.second->reset();
+                GenValue::reset();
                 for(auto con : containers)
                     con.second->fill();
             }
         }
+
+        /* template <typename T> */
+        /* virtual T* get_field(const std::string& field_name) = 0; */
+
         void add_value(GenValue *value, const std::string& value_name ){
+            /* Adds a value to the dataset's list of known value objects. Note
+             * that all new values are automatically kept track of by
+             * GenValue::values so this is only needed if one wants to recall
+             * the value by name.
+             */
             values[value_name] = value;
         }
         GenValue* get_value(std::string value_name){
-            return values[value_name];
+            return values.at(value_name);
         }
 
         void add_container(GenContainer *container){
             containers[container->get_name()] = container;
         }
         GenContainer* get_container(std::string container_name){
-            return containers[container_name];
+            return containers.at(container_name);
         }
 };
 }

+ 20 - 73
filter.hpp

@@ -1,6 +1,7 @@
 #ifndef filter_h
 #define filter_h
 #include <iostream>
+#include <functional>
 #include "value.hpp"
 /* A Filter is a special type of derived value that can only return a boolean.
  * Container objects have a vector of filters that control if a "fill" call
@@ -8,94 +9,40 @@
  */
 namespace filval {
 
-class Filter : public DerivedValue<bool>{ };
+class GenFilter : public DerivedValue<bool>{};
 
-
-class FilterAnd : public Filter {
-    protected:
-        Filter *filterA;
-        Filter *filterB;
-    void update_value(){
-        value = filterA->get_value() && filterB->get_value();
-    }
-    public:
-        FilterAnd(Filter *filterA, Filter *filterB)
-            :filterA(filterA), filterB(filterB){ }
-};
-
-class FilterOr : public Filter {
+class Filter : public GenFilter{
     private:
-        Filter *filterA;
-        Filter *filterB;
-    void update_value(){
-        value = filterA->get_value() || filterB->get_value();
-    }
-    public:
-        FilterOr(Filter *filterA, Filter *filterB)
-            :filterA(filterA), filterB(filterB){ }
-};
-
-class FilterInv : public Filter {
-    private:
-        Filter *filter;
-    void update_value(){
-        value = !filter->get_value();
-    }
-    public:
-        FilterInv(Filter *filter)
-            :filter(filter){ }
-};
-
-template <typename T>
-class FilterGreaterThan : public Filter {
-    private:
-        Value<T> *filter_value;
-        Value<T> *range_low;
+        std::function<bool()> filter_function;
         void update_value(){
-            value = filter_value->get_value() > range_low->get_value();
+            value = filter_function();
         }
     public:
-        FilterGreaterThan(GenValue* filter_value, GenValue* range_low)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)),
-             range_low(dynamic_cast<Value<T>*>(range_low)) { }
+        Filter(std::function<bool()> filter_function)
+          :filter_function(filter_function){ }
 
-        FilterGreaterThan(GenValue* filter_value, T range_low)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)){
-            this->range_low = new ConstantValue<T>(range_low);
+        Filter* operator*(Filter *f){
+            return new Filter([this, f](){return this->get_value() && f->get_value();});
         }
-};
 
-template <typename T>
-class FilterLessThan : public Filter {
-    private:
-        Value<T> *filter_value;
-        Value<T> *range_high;
-        void update_value(){
-            value = filter_value->get_value() < range_high->get_value();
+        Filter* operator+(Filter *f){
+            return new Filter([this, f](){return this->get_value() || f->get_value();});
         }
-    public:
-        FilterLessThan(GenValue* filter_value, GenValue* range_high)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)),
-             range_high(dynamic_cast<Value<T>*>(range_high)) { }
 
-        FilterLessThan(GenValue* filter_value, T range_high)
-            :filter_value(dynamic_cast<Value<T>*>(filter_value)){
-            this->range_high = new ConstantValue<T>(range_high);
+        Filter* operator!(){
+            return new Filter([this](){return !this->get_value();});
         }
 };
 
-
 template <typename T>
-class RangeFilter : public FilterAnd {
+class RangeFilter : public Filter{
+    private:
     public:
-        RangeFilter(Value<T> *filter_value, Value<T> *range_low, Value<T> *range_high){
-            this->filterA = new FilterLessThan<T>(filter_value, range_high);
-            this->filterB = new FilterGreaterThan<T>(filter_value, range_low);
-         }
-        RangeFilter(Value<T> *filter_value, T range_low, T range_high){
-            this->filterA = new FilterLessThan<T>(filter_value, range_high);
-            this->filterB = new FilterGreaterThan<T>(filter_value, range_low);
-        }
+        RangeFilter(Value<T>* test_value, T range_low, T range_high):
+          Filter([test_value, range_low, range_high]{
+                  T val = test_value->get_value();
+                  return (val >= range_low) && (val < range_high);
+                  }){ }
 };
 }
 #endif // filter_h

+ 154 - 44
value.hpp

@@ -2,85 +2,114 @@
 #define value_hpp
 #include <iostream>
 #include <utility>
+#include <algorithm>
 #include <map>
+#include <vector>
+#include <tuple>
+#include <initializer_list>
+#include <functional>
 
 namespace filval{
 
 class GenValue{
+    private:
+        inline static std::vector<GenValue*> values;
+        virtual void _reset() = 0;
     public:
-        virtual void reset() = 0;
+        GenValue(){
+            values.push_back(this);
+        }
+        static void reset(){
+            for (auto val : values){
+                val->_reset();
+            }
+        }
 };
 typedef std::map<std::string, GenValue*> ValueSet;
 
-/* class ValueSet: public std::map<std::string, GenValue*>{ */
-/*     public: */
-/*         GenValue*& operator[](const std::string& key){ */
-/*             GenValue*& value = (*this)[key]; */
-/*             if (value == NULL){ */
-/*                 std::cerr << "ERROR: key \""<<key */
-/*                     <<"\" not in valueset" << std::endl; */
-/*             } */
-/*             return value; */
-/*         } */
-/* }; */
-
 
-template <typename V>
+template <typename T>
 class Value : public GenValue{
     public:
-        virtual V& get_value() = 0;
+        Value(): GenValue(){}
+        virtual T& get_value() = 0;
 };
 
 
-template <typename V>
-class ObservedValue : public Value<V>{
+template <typename T>
+class ObservedValue : public Value<T>{
     /* For "observed" values, there is nothing to calculate since this is
      * merely a wrapper around a field in the observation. A pointer to the
      * value is kept and it's value is read when requested.
      */
     private:
-        V *val_ref;
+        T *val_ref;
+        void _reset(){ }
     public:
-        ObservedValue(V *val_ref)
-            : val_ref(val_ref){}
-        V& get_value(){
+        ObservedValue(T* val_ref)
+          :Value<T>(),
+           val_ref(val_ref){ }
+        T& get_value(){
             return *val_ref;
         }
-        void reset(){ }
 };
 
 
-template <typename V>
-class DerivedValue : public Value<V>{
+template <typename T>
+class DerivedValue : public Value<T>{
     /* A "derived" value is the result of some sort of calculation. Since it is
      * desireable for the calculation to occur at most a single time for each
      * observation, the result of the calculation is stored in the object. be
      * sure that "reset" is called between processing observations to force a
      * re-calculation.
      */
+    private:
+        void _reset(){
+            value_valid = false;
+        }
     protected:
-        V value; // The value to be calculated
+        T value;
         bool value_valid;
 
         virtual void update_value() = 0;
     public:
-        V& get_value(){
+        DerivedValue() :Value<T>(), value_valid(false) { }
+
+        T& get_value(){
             if (!value_valid){
-                /* std::cout << "updating value!\n"; */
                 update_value();
                 value_valid = true;
             }
             return value;
         }
+};
 
-        void reset(){
-            value_valid = false;
+template <typename T>
+class WrapperVector : public DerivedValue<std::vector<T> >{
+    private:
+        Value<int>* size;
+        Value<T*>* data;
+
+        void update_value(){
+            int n = size->get_value();
+            T* data_ref = data->get_value();
+            this->value.resize(n);
+            for (int i=0; i<n; i++){
+                this->value[i] = *(data_ref+i);
+            }
         }
-};
 
+    public:
+        WrapperVector(Value<int>* _size, Value<T*>* _data)
+          :DerivedValue<std::vector<T> >(),
+           size(_size), data(_data){ }
+        WrapperVector(ValueSet *values, const std::string &label_size, const std::string &label_data)
+          :WrapperVector(dynamic_cast<Value<int>*>(values->at(label_size)),
+                         dynamic_cast<Value<T*>*>(values->at(label_data))) { }
+};
 
 template <typename T1, typename T2>
-class DerivedPair : public DerivedValue<std::pair<T1, T2> >{
+class Pair : public DerivedValue<std::pair<T1, T2> >{
     protected:
         std::pair<Value<T1>*, Value<T2>* > value_pair;
         void update_value(){
@@ -88,27 +117,108 @@ class DerivedPair : public DerivedValue<std::pair<T1, T2> >{
             this->value.second = value_pair.second->get_value();
         }
     public:
-        DerivedPair(ValueSet *values, const std::string &label1, const std::string &label2){
-            ValueSet &valueSet = *values;
-            value_pair.first  = (Value<T1>*) valueSet[label1];
-            value_pair.second = (Value<T2>*) valueSet[label2];
-         }
-        DerivedPair(Value<T1> *value1, Value<T2> *value2){
-            value_pair.first  = value1;
-            value_pair.second = value2;
-         }
+        Pair(Value<T1> *value1, Value<T2> *value2)
+          :DerivedValue<std::pair<T1, T2> >(),
+           value_pair(value1, value2){ }
+        Pair(ValueSet *values, const std::string &label1, const std::string &label2)
+          :Pair((Value<T1>*) values->at(label1),
+                (Value<T1>*) values->at(label2)){ }
+};
+
+template <typename R, typename T>
+class ZipMapFour : public DerivedValue<std::vector<R> >{
+    private:
+        std::function<R(T, T, T, T)> f;
+        Value<std::vector<T> >* v1;
+        Value<std::vector<T> >* v2;
+        Value<std::vector<T> >* v3;
+        Value<std::vector<T> >* v4;
 
+        void update_value(){
+            std::vector<T> v1_val = v1->get_value();
+            std::vector<T> v2_val = v2->get_value();
+            std::vector<T> v3_val = v3->get_value();
+            std::vector<T> v4_val = v4->get_value();
+
+            int n;
+            std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
+            this->value.resize(n);
+            for (int i=0; i<n; i++){
+                this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
+            }
+        }
+
+    public:
+        ZipMapFour(std::function<R(T, T, T, T)> f,
+                   Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
+                   Value<std::vector<T> >* v3, Value<std::vector<T> >* v4)
+          :DerivedValue<std::vector<R> >(),
+           f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
+        ZipMapFour(std::function<R(T, T, T, T)> f,
+                   ValueSet *values,
+                   const std::string &label1,
+                   const std::string &label2,
+                   const std::string &label3,
+                   const std::string &label4)
+          :ZipMapFour(f,
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label1)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label2)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label3)),
+                      dynamic_cast<Value<std::vector<T> >*>(values->at(label4))){ }
+};
+
+template <typename T>
+class Reduce : public DerivedValue<T>{
+    private:
+        std::function<T(std::vector<T>)> reduce;
+        Value<std::vector<T> >* v;
+        void update_value(){
+            this->value = reduce(v->get_value());
+        }
+    public:
+        Reduce(std::function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
+          :DerivedValue<T>(),
+           reduce(reduce), v(v) { }
+};
+
+template <typename R, typename... T>
+class MultiFunc : public DerivedValue<R>{
+    private:
+        std::function<R(T...)> f;
+        std::tuple<T...> value_tuple;
+
+        void update_value(){
+            this->value = f(value_tuple);
+        }
+
+    public:
+        MultiFunc(std::function<R(std::tuple<T...>)> f, T... varargs)
+          :f(f),
+           value_tuple(varargs...){ }
+};
+
+template <typename T>
+class BoundValue : public DerivedValue<T>{
+    /* A "bound" value has it's dependencies bound into a function object. */
+    protected:
+        std::function<T()> f;
+        void update_value(){
+            this->value = f();
+        }
+    public:
+        BoundValue(std::function<T()> f)
+          :f(f) { }
 };
 
-template <typename V>
-class ConstantValue : public DerivedValue<V>{
+template <typename T>
+class ConstantValue : public DerivedValue<T>{
     protected:
-        V const_value;
+        T const_value;
         void update_value(){
             this->value = const_value;
         }
     public:
-        ConstantValue(V const_value)
+        ConstantValue(T const_value)
             :const_value(const_value) { }
 };
 }