Field set struct in MOSES

From OpenCog
Jump to: navigation, search

MOSES defines a field as a means of densely packing variable values into an array. A field set creates a simple, optimally compact representation of a set of continuous and discrete variables. This is made possible by assuming that the number of bits in the encoding of the smallest discrete variable is either a multiple of bits_per_packed_t, or is equal in size to or larger than the number of bits in the encoding of the largest continuious variable. Similarly the smallest continuous variable must be a multiple of bits_per_packed_t, or be larger (in bits) than the largest discrete variable.

source code

struct field_set {
    typedef unsigned int arity_t;
    typedef std::size_t size_t;

   // ...
 
    struct field {
        field() { }
        field(arity_t w, size_t ma, size_t mi)
                : width(w), major_offset(ma), minor_offset(mi) { }
        arity_t width;
        size_t major_offset, minor_offset;
    };
    typedef vector<field>::const_iterator field_iterator;

    struct disc_spec {
        disc_spec(arity_t a) : arity(a) { }
        arity_t arity;
        bool operator<(const disc_spec& rhs) const { //sort descending by arity
            return arity > rhs.arity;
        }
        bool operator==(const disc_spec& rhs) const { //don't know why this is needed
            return arity == rhs.arity;
        }
    };

    struct contin_spec {
        contin_spec(contin_t m, contin_t ss, contin_t ex, arity_t d)
                : mean(m), step_size(ss), expansion(ex), depth(d) { }
        contin_t mean, step_size, expansion;
        arity_t depth;
        bool operator<(const contin_spec& rhs) const { //sort descending by depth
            return depth > rhs.depth;
        }
        bool operator==(const contin_spec& rhs) const { //don't know why this is needed
            return (mean == rhs.mean &&
                    step_size == rhs.step_size &&
                    expansion == rhs.expansion &&
                    depth == rhs.depth);
        }

        //half the smallest possible difference between two values represented
        //according to the spec
        contin_t epsilon() const {
            return step_size / contin_t(size_t(1) << depth);
        }

        static const disc_t Stop;
        static const disc_t Left;
        static const disc_t Right;
    };
    struct contin_stepper {
        contin_stepper(const contin_spec& c_)
                : c(c_), value(c.mean),
                _all_left(true), _all_right(true), _step_size(c.step_size) { }
        const contin_spec& c;
        contin_t value;

        void left() {
            if (_all_left) {
                value -= _step_size;
                _step_size *= c.expansion;
                _all_right = false;
            } else {
                if (_all_right) {
                    _all_right = false;
                    _step_size /= (c.expansion * 2);
                }
                value -= _step_size;
                _step_size /= 2;
            }
        }
        void right() {
            if (_all_right) {
                value += _step_size;
                _step_size *= c.expansion;
                _all_left = false;
            } else {
                if (_all_left) {
                    _all_left = false;
                    _step_size /= (c.expansion * 2);
                }
                value += _step_size;
                _step_size /= 2;
            }
        }
    protected:
        bool _all_left;
        bool _all_right;
        contin_t _step_size;
    };
    struct onto_spec {
        onto_spec(const onto_tree& t)
                : tr(&t), depth(t.max_depth(t.begin())),
                branching(opencog::next_power_of_two(1 + t.max_branching(t.begin()))) { }
        bool operator<(const onto_spec& rhs) const { //sort descending by size
            return (depth*branching > rhs.depth*rhs.branching);
        }

        const onto_tree* tr;
        size_t depth, branching;

        bool operator==(const onto_spec& rhs) const { //don't know why this is needed
            return (depth == rhs.depth && branching == rhs.branching && *tr == *(rhs.tr));
        }

        static const disc_t Stop;
        static disc_t to_child_idx(disc_t d) {
            return d -1;
        }
        static disc_t from_child_idx(disc_t d) {
            return d + 1;
        }
    };
    typedef boost::variant<onto_spec, contin_spec, disc_spec> spec;
     
   // ......

protected:
    vector<field> _fields;
    vector<disc_spec> _disc;
    vector<contin_spec> _contin;
    vector<onto_spec> _onto;
    size_t _nbool;
    field_iterator _contin_start, _disc_start;
    
    // ...
 
}

field struct

The field struct provides the information needed to get/set the value of some variable(of any type) in an instance (i.e. a packed/vector).

The *major_offset* is the index of the element in the instance where the value of the field is stored in. But since there may be values of many different variables stored in the same packed_t value of the instance,this is not enough. We need *minor_offset* to tell us where inside the packed_t value instance[major_offset] the value is stored. And we need *width* to tell us how many bits (starting at this position) are used to encode the value.

The following picture shows that how the filed to express the value in an instance: Field.jpeg

contin_spec struct

The basic idea is to represent continuous quantities, conceptually, as variable-length sequences of bits, with a simplicity prior towards shorter sequences. Bit-sequences are mapped to continuous values using a simple information-theoretic approach. (i.e. consider representing a value in the range (-1,1) with a uniform prior). There is a paper about the how to represent continous quantities , you could find it here

onto_spec struct

TODO: