Example #1
0
    def test_repr(self):
        fd1 = fdict(a=1, b=2)
        T.assert_equal(repr(fd1), "fdict({'a': 1, 'b': 2})")
        T.assert_equal(eval(repr(fd1)), fd1)

        fd2 = fdict(c=3, **fd1)
        T.assert_equal(repr(fd2), "fdict({'a': 1, 'c': 3, 'b': 2})")
        T.assert_equal(eval(repr(fd2)), fd2)
Example #2
0
    def test_can_hash(self):
        # Only immutable objects are hashable, and hashable objects can be dict keys.
        fd1 = fdict(a=1, b=2)
        fd2 = fdict({'a':1, 'b':2})

        mydict = {fd1:1}
        mydict[fd2] = 2

        T.assert_equal(mydict[fd1], 2)
Example #3
0
    def test_dunder_init(self):
        fd = fdict(a=1)
        assert fd == {'a': 1}, dict(fd)

        # Implemented naively, __init__ would re-set the value of our immutable object.
        fd.__init__(b=2)
        assert fd == {'a': 1}, dict(fd)
Example #4
0
    def test_cheap_hash(self):
        import mock
        import __builtin__
        with mock.patch.object(__builtin__, 'hash', wraps=hash) as mock_hash:
            fd = fdict(a=1)

            T.assert_equal((('a', 1),).__hash__(), fd.__hash__())
            T.assert_equal(1, mock_hash.call_count)

            T.assert_equal((('a', 1),).__hash__(), fd.__hash__())
            T.assert_equal(1, mock_hash.call_count)
Example #5
0
    def copy(mcs, children=None, properties=None):
        """Return an (altered) copy of this object."""
        # Make a copy, with altered children and/or properties attributes.
        attrs = mcs.__dict__.copy()

        if children is not None:
            attrs['children'] = tuple(children)

        if properties:
            attrs['properties'] = fdict(mcs.properties).update(properties)
            attrs['properties'] = fdict(
                (key, val) for key, val in attrs['properties'].items()
                if val is not token.undefined)

        mcs_copy = super(tokenType, mcs).__new__(
            # Inherit attributes of the copied class
            mcs,
            mcs.__name__,
            (token, ),
            attrs,
        )
        return mcs_copy
Example #6
0
    def test_no_vars(self):
        """
        To allocate a .__dict__ attribute of this object means that we're
        allocating a second, mutable dictionary as part of our frozendict.
        This would be a waste of memory as well as yielding pretty nonsensical
        semantics wrt immutability.
        """
        fd = fdict(a=1)
        with T.assert_raises(TypeError):
            vars(fd)

        with T.assert_raises(AttributeError):
            fd.__dict__
Example #7
0
    def copy(mcs, children=None, properties=None):
        """Return an (altered) copy of this object."""
        # Make a copy, with altered children and/or properties attributes.
        attrs = mcs.__dict__.copy()

        if children is not None:
            attrs['children'] = tuple(children)

        if properties:
            attrs['properties'] = fdict(mcs.properties).update(properties)
            attrs['properties'] = fdict(
                (key, val)
                for key, val in attrs['properties'].items()
                if val is not token.undefined
            )

        mcs_copy = super(tokenType, mcs).__new__(
            # Inherit attributes of the copied class
            mcs,
            mcs.__name__,
            (token,),
            attrs,
        )
        return mcs_copy
Example #8
0
 def test_update(self):
     ################################
     # a b c d e f g h i j k l m n o
     # * * * * * * * *
     # * * * *         * * * *
     # * *     * *     * *     * *
     # *   *   *   *   *   *   *   *
     fd = fdict(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8)
     fd2 = fd.update(
             dict(a=9, b=10, c=11, d=12, i=13, j=14, k=15, l=16),
             (
                 (key, val)
                 for key, val in zip(
                     ('a', 'b', 'e', 'f', 'i', 'j', 'm', 'n'),
                     range(17, 25),
                 )
             ),
             a=25, c=26, e=27, g=28, i=29, k=30, m=31, o=32
     )
     expected = dict(
             a=25, b=18, c=26, d=12, e=27, f=20, g=28, h=8,
             i=29, j=22, k=30, l=16, m=31, n=24, o=32,
     )
     assert fd2 == expected
def test___WALTER_2015___RoboAI___MidTerm_Q1():
    """test: WALTER (2015) "Planning, Learning & Estimation in Robotics & A.I.": Mid-Term Exam, Question 1"""

    # Number of Time Periods
    T = 2

    state_prior = PMF(dict.fromkeys((('S', 0),)),
                      {fdict({('S', 0): 1}): 1 / 3,
                       fdict({('S', 0): 2}): 1 / 3,
                       fdict({('S', 0): 3}): 1 / 3})
    state_transition_template = PMF(dict.fromkeys((('S', -1), ('S', 0))),
                                    {fdict({('S', -1): 1, ('S', 0): 1}): .2,
                                     fdict({('S', -1): 1, ('S', 0): 2}): .3,
                                     fdict({('S', -1): 1, ('S', 0): 3}): .5,
                                     fdict({('S', -1): 2, ('S', 0): 1}): .2,
                                     fdict({('S', -1): 2, ('S', 0): 2}): .7,
                                     fdict({('S', -1): 2, ('S', 0): 3}): .1,
                                     fdict({('S', -1): 3, ('S', 0): 1}): .4,
                                     fdict({('S', -1): 3, ('S', 0): 2}): .2,
                                     fdict({('S', -1): 3, ('S', 0): 3}): .4},
                                    cond={('S', -1): None})
    observation_template = PMF(dict.fromkeys((('S', 0), ('Z', 0))),
                               {fdict({('S', 0): 1, ('Z', 0): 1}): .6,
                                fdict({('S', 0): 1, ('Z', 0): 2}): .1,
                                fdict({('S', 0): 1, ('Z', 0): 3}): .3,
                                fdict({('S', 0): 2, ('Z', 0): 1}): .1,
                                fdict({('S', 0): 2, ('Z', 0): 2}): .7,
                                fdict({('S', 0): 2, ('Z', 0): 3}): .2,
                                fdict({('S', 0): 3, ('Z', 0): 1}): .2,
                                fdict({('S', 0): 3, ('Z', 0): 2}): .3,
                                fdict({('S', 0): 3, ('Z', 0): 3}): .5},
                               cond={('S', 0): None})
    hmm = HMM('S', 'Z', state_prior, state_transition_template, observation_template)

    # Set up Probability Factors / Joint Probability Distributions
    print('\nPROBLEM SETUPS:\n')

    print('Prob(S_0) =')
    hmm.state_prior_pdf.pprint()

    for t in range(1, T + 1):
        print('Prob(S_%i | S_%i) =' % (t, t - 1))
        hmm.transition_pdf(t).pprint()

    for t in range(T + 1):
        print('Prob(Z_%i | S_%i) =' % (t, t))
        hmm.observation_pdf(t).pprint()

    all_z = {0: 2, 1: 3, 2: 1}
    print('actual z values =\n', all_z)

    print('\nFORWARD-BACKWARD ALGORITHM:\n')

    print('"Forward" Probabilities:\n')
    forward = hmm.forward_pdf(range(T + 1), all_z)

    for t in range(T + 1):
        print('Prob(S_%i, z up to z_%i) =' % (t, t))
        forward[t].pprint()

    alpha_0 = PMF(dict.fromkeys((('S', 0), ('Z', 0))),
                  {fdict({('S', 0): 1, ('Z', 0): 2}): .1 / 3,
                   fdict({('S', 0): 2, ('Z', 0): 2}): .7 / 3,
                   fdict({('S', 0): 3, ('Z', 0): 2}): .3 / 3},
                  scope={('Z', 0): 2})
    forward_0___check = forward[0].allclose(alpha_0)

    alpha_1 = PMF(dict.fromkeys((('S', 1), ('Z', 0), ('Z', 1))),
                  {fdict({('S', 1): 1, ('Z', 0): 2, ('Z', 1): 3}): .084 / 3,
                   fdict({('S', 1): 2, ('Z', 0): 2, ('Z', 1): 3}): .116 / 3,
                   fdict({('S', 1): 3, ('Z', 0): 2, ('Z', 1): 3}): .12 / 3},
                  scope={('Z', 0): 2, ('Z', 1): 3})
    forward_1___check = forward[1].allclose(alpha_1)

    alpha_2 = PMF(dict.fromkeys((('S', 2), ('Z', 0), ('Z', 1), ('Z', 2))),
                  {fdict({('S', 2): 1, ('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}): .0528 / 3,
                   fdict({('S', 2): 2, ('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}): .013 / 3,
                   fdict({('S', 2): 3, ('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}): .0203 / 3},
                  scope={('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1})
    forward_2___check = forward[2].allclose(alpha_2, atol=1e-2)

    print('"Backward" Probabilities:\n')
    backward = hmm.backward_factor(range(T + 1), all_z)

    for t in reversed(range(T + 1)):   # Recursively compute Backward factors
        print('Prob(z_%i to %i | S_%i) =' % (t + 1, T, t))
        backward[t].pprint()

    beta_2 = PMF(dict.fromkeys((('S', 2),)),
                 {fdict({('S', 2): 1}): 1.,
                  fdict({('S', 2): 2}): 1.,
                  fdict({('S', 2): 3}): 1.},
                 cond={('S', 2): None})
    backward_2___check = backward[2].allclose(beta_2)

    beta_1 = PMF(dict.fromkeys((('S', 1), ('Z', 2))),
                 {fdict({('S', 1): 1, ('Z', 2): 1}): .25,
                  fdict({('S', 1): 2, ('Z', 2): 1}): .21,
                  fdict({('S', 1): 3, ('Z', 2): 1}): .34},
                 cond={('S', 1): None},
                 scope={('Z', 2): 1})
    backward_1___check = backward[1].allclose(beta_1)

    beta_0 = PMF(dict.fromkeys((('S', 0), ('Z', 1), ('Z', 2))),
                 {fdict({('S', 0): 1, ('Z', 1): 3, ('Z', 2): 1}): .1126,
                  fdict({('S', 0): 2, ('Z', 1): 3, ('Z', 2): 1}): .0614,
                  fdict({('S', 0): 3, ('Z', 1): 3, ('Z', 2): 1}): .1064},
                 cond={('S', 0): None},
                 scope={('Z', 1): 3, ('Z', 2): 1})
    backward_0___check = backward[0].allclose(beta_0)

    print('Probability of each X conditional on all z values:\n')
    infer_state = hmm.infer_state(range(T + 1), all_z)
    for t in range(T + 1):
        print('Prob(S_%i | all z) =' % t)
        infer_state[t].pprint()

    infer_0 = PMF(dict.fromkeys((('S', 0), ('Z', 0), ('Z', 1), ('Z', 2))),
                  {fdict({('S', 0): 1}): .0038,
                   fdict({('S', 0): 2}): .0143,
                   fdict({('S', 0): 3}): .0106},
                  cond={('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}).norm()
    infer_0.pprint()
    infer_0___check = infer_state[0].allclose(infer_0, atol=1e-1)

    infer_1 = PMF(dict.fromkeys((('S', 1), ('Z', 0), ('Z', 1), ('Z', 2))),
                  {fdict({('S', 1): 1}): .007,
                   fdict({('S', 1): 2}): .0081,
                   fdict({('S', 1): 3}): .0136},
                  cond={('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}).norm()
    infer_1.pprint()
    infer_1___check = infer_state[1].allclose(infer_1, atol=1e-2)

    infer_2 = PMF(dict.fromkeys((('S', 2), ('Z', 0), ('Z', 1), ('Z', 2))),
                  {fdict({('S', 2): 1}): .0176,
                   fdict({('S', 2): 2}): .0043,
                   fdict({('S', 2): 3}): .0068},
                  cond={('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1}).norm()
    infer_2.pprint()
    infer_2___check = infer_state[2].allclose(infer_2, atol=1e-1)

    print('MAP of each X:\n')
    for t in range(T + 1):
        print('MAP Prob(S_%i | all z) =' % t)
        infer_state[t].max().pprint()

    print('\nVITERBI ALGORITHM:\n')

    all_z = [[2]]
    all_z += [all_z[0] + [3]]
    all_z += [all_z[1] + [1]]
    map_joint_distributions = []
    for t in range(T + 1):
        print('Most Likely Joint Distribution with actual z values up to z_%i:' % t)
        map_joint_distributions += [hmm.max_a_posteriori_joint_distributions(all_z[t])]
        map_joint_distributions[t].pprint()

    map_0 = PMF(dict.fromkeys((('S', 0), ('Z', 0))),
                {fdict({('S', 0): 2, ('Z', 0): 2}): .7 / 3},
                scope={('Z', 0): 2})
    map_0___check = map_joint_distributions[0].allclose(map_0)

    map_1 = PMF(dict.fromkeys((('S', 0), ('Z', 0), ('S', 1), ('Z', 1))),
                 {fdict({('S', 0): 2, ('Z', 0): 2, ('S', 1): 2, ('Z', 1): 3}): .0327},
                 scope={('Z', 0): 2, ('Z', 1): 3})
    map_1___check = map_joint_distributions[1].allclose(map_1, atol=1e-3)

    map_2 = PMF(dict.fromkeys((('S', 0), ('Z', 0), ('S', 1), ('Z', 1), ('S', 2), ('Z', 2))),
                {fdict({('S', 0): 3, ('Z', 0): 2, ('S', 1): 3, ('Z', 1): 3, ('S', 2): 1, ('Z', 2): 1}): .0048},
                scope={('Z', 0): 2, ('Z', 1): 3, ('Z', 2): 1})
    map_2___check = map_joint_distributions[2].allclose(map_2)

    map_state_sequence = hmm.max_a_posteriori_state_sequence(all_z[2])
    print(map_state_sequence)
    map_state_sequence___answer = [3, 3, 1]
    map_state_sequence___check = map_state_sequence == map_state_sequence___answer

    assert forward_0___check & forward_1___check & forward_2___check &\
        backward_0___check & backward_1___check & backward_2___check &\
        infer_0___check & infer_1___check & infer_2___check &\
        map_0___check & map_1___check & map_2___check & map_state_sequence___check
Example #10
0
 def test_is_immutable2(self):
     # some simple frozendict implementations would mutate here.
     fd = fdict(a=1)
     with T.assert_raises(TypeError):
         dict.update(fd, {'a':2})
Example #11
0
 def test_no_attribute_deletion(self):
     fd = fdict()
     with T.assert_raises(AttributeError):
         del fd.copy
def test___WALTER_2015___RoboAI___ProbSet1_Q1():
    """test: WALTER (2015) "Planning, Learning & Estimation in Robotics & A.I.": Problem Set 1, Question 1"""
    p_C = PMF(dict.fromkeys(('C',)),
              {fdict(C='a'): .3,
               fdict(C='n'): .5,
               fdict(C='l'): .2})
    p_T1_on_C = PMF(dict.fromkeys(('C', 'T1')),
                    {fdict(C='a', T1=0): .3,
                     fdict(C='a', T1=1): .7,
                     fdict(C='n', T1=0): .5,
                     fdict(C='n', T1=1): .5,
                     fdict(C='l', T1=0): .8,
                     fdict(C='l', T1=1): .2},
                    cond=dict(C=None))
    p_T2_on_C = PMF(dict.fromkeys(('C', 'T2')),
                    {fdict(C='a', T2=0): .2,
                     fdict(C='a', T2=1): .8,
                     fdict(C='n', T2=0): .6,
                     fdict(C='n', T2=1): .4,
                     fdict(C='l', T2=0): .9,
                     fdict(C='l', T2=1): .1},
                    cond=dict(C=None))
    p_D_on_T1_T2 = PMF(dict.fromkeys(('T1', 'T2', 'D')),
                       {fdict(T1=0, T2=0, D=0): 1.,
                        fdict(T1=0, T2=0, D=1): .0,
                        fdict(T1=0, T2=1, D=0): 1.,
                        fdict(T1=0, T2=1, D=1): .0,
                        fdict(T1=1, T2=0, D=0): .0,
                        fdict(T1=1, T2=0, D=1): 1.,
                        fdict(T1=1, T2=1, D=0): .0,
                        fdict(T1=1, T2=1, D=1): 1.},
                       cond=dict(T1=None, T2=None))

    p_T1 = (p_C * p_T1_on_C).marg('C')
    p_T1.pprint()
    p_T1___answer = PMF(dict.fromkeys(('T1',)),
                        {fdict(T1=0): .5,
                         fdict(T1=1): .5})
    p_T1___check = p_T1.allclose(p_T1___answer)

    p_T2 = (p_C * p_T2_on_C).marg('C')
    p_T2.pprint()
    p_T2___answer = PMF(dict.fromkeys(('T2',)),
                        {fdict(T2=0): .54,
                         fdict(T2=1): .46})
    p_T2___check = p_T2.allclose(p_T2___answer)

    p_T1_T2 = (p_C * p_T1_on_C * p_T2_on_C).marg('C')
    p_T1_T2.pprint()
    p_T1_T2___answer = PMF(dict.fromkeys(('T1', 'T2')),
                           {fdict(T1=0, T2=0): .312,
                            fdict(T1=0, T2=1): .188,
                            fdict(T1=1, T2=0): .228,
                            fdict(T1=1, T2=1): .272})
    p_T1_T2___check = p_T1_T2.allclose(p_T1_T2___answer)

    p_T1_p_T2 = p_T1 * p_T2
    p_T1_p_T2.pprint()

    p_T1_T2_on_C_equal_n = (p_C * p_T1_on_C * p_T2_on_C).cond(C='n').norm()
    p_T1_T2_on_C_equal_n.pprint()
    p_T1_T2_on_C_equal_n___answer = PMF(dict.fromkeys(('C', 'T1', 'T2')),
                                        {fdict(T1=0, T2=0): .3,
                                         fdict(T1=0, T2=1): .2,
                                         fdict(T1=1, T2=0): .3,
                                         fdict(T1=1, T2=1): .2},
                                        cond=dict(C='n'))
    p_T1_T2_on_C_equal_n___check = p_T1_T2_on_C_equal_n.allclose(p_T1_T2_on_C_equal_n___answer)

    p_T1_on_C_equal_n = p_T1_on_C.at(C='n')
    p_T1_on_C_equal_n.pprint()
    p_T2_on_C_equal_n = p_T2_on_C.at(C='n')
    p_on_T1_T2_and_D_equal_1 = p_D_on_T1_T2.cond(D=1)
    p_T1_T2_on_C_equal_n_and_D_equal_1 = (p_T1_on_C_equal_n * p_T2_on_C_equal_n * p_on_T1_T2_and_D_equal_1).norm()
    p_T1_T2_on_C_equal_n_and_D_equal_1.pprint()

    p_T1_T2_on_C_equal_n_and_D_equal_1___alternative =\
        (p_C * p_T1_on_C * p_T2_on_C * p_D_on_T1_T2).cond(C='n', D=1).norm()
    p_T1_T2_on_C_equal_n_and_D_equal_1___alternative.pprint()

    p_T1_T2_on_C_equal_n_and_D_equal_1___answer = PMF(dict.fromkeys(('C', 'T1', 'T2', 'D')),
                                                      {fdict(T1=0, T2=0): .0,
                                                       fdict(T1=0, T2=1): .0,
                                                       fdict(T1=1, T2=0): .6,
                                                       fdict(T1=1, T2=1): .4},
                                                      cond=dict(C='n', D=1))
    p_T1_T2_on_C_equal_n_and_D_equal_1___answer.pprint()
    p_T1_T2_on_C_equal_n_and_D_equal_1___check =\
        p_T1_T2_on_C_equal_n_and_D_equal_1.allclose(p_T1_T2_on_C_equal_n_and_D_equal_1___alternative,
                                                    p_T1_T2_on_C_equal_n_and_D_equal_1___answer)

    assert p_T1___check & p_T2___check & p_T1_T2___check & p_T1_T2_on_C_equal_n___check &\
        p_T1_T2_on_C_equal_n_and_D_equal_1___check
Example #13
0
 def test_no_attributes_allowed(self):
     fd = fdict()
     with T.assert_raises(AttributeError):
         fd.x = 1
Example #14
0
    def test_is_immutable(self):
        fd = fdict(a=1)
        T.assert_equal(fd['a'], 1)

        with T.assert_raises(TypeError):
            fd['a'] = 2
Example #15
0
 def test_cheap_copy(self):
     fd = fdict()
     T.assert_is(fd, fd.copy())
Example #16
0
class tokenType(type):
    """The type for token classes."""
    children = ()
    properties = fdict()
    undefined = object()

    def __repr__(cls):
        return pformat(cls.__primitive__())

    def __primitive__(mcs):
        # This is (so far) primarily to make the structure easily viewable for debugging.
        result = (mcs.__name__, )
        if mcs.children:
            result += tuple(mcs.children)
        if mcs.properties:
            result += (dict(mcs.properties), )
        return result

    def __eq__(cls, other):
        if isinstance(other, tokenType):
            return cls.__primitive__() == other.__primitive__()
        else:
            return NotImplemented

    def __ne__(cls, other):
        if isinstance(other, tokenType):
            return cls.__primitive__() != other.__primitive__()
        else:
            return NotImplemented

    def __len__(cls):
        return len(cls.children)

    def __iter__(cls):
        return iter(cls.children)

    def copy(mcs, children=None, properties=None):
        """Return an (altered) copy of this object."""
        # Make a copy, with altered children and/or properties attributes.
        attrs = mcs.__dict__.copy()

        if children is not None:
            attrs['children'] = tuple(children)

        if properties:
            attrs['properties'] = fdict(mcs.properties).update(properties)
            attrs['properties'] = fdict(
                (key, val) for key, val in attrs['properties'].items()
                if val is not token.undefined)

        mcs_copy = super(tokenType, mcs).__new__(
            # Inherit attributes of the copied class
            mcs,
            mcs.__name__,
            (token, ),
            attrs,
        )
        return mcs_copy

    # Be immutable.
    def __setattr__(cls, key, value=None):
        raise TypeError(
            "{name} objects are read-only".format(name=type(cls).__name__))

    def __delattr__(cls, key):
        raise TypeError(
            "{name} objects are read-only".format(name=type(cls).__name__))

    def __getattribute__(cls, attr):
        """Emulate type_getattro() in Objects/typeobject.c,
        except descriptors can be bound to classes too.
        """
        if attr == '__new__':
            val = type.__getattribute__(cls, attr)
            # python specifies type.__new__ as a special case. sadface.
            # Otherwise you get the metaclass as the first *two* arguments.
            result = val.__get__(None, type(cls))
        else:
            val = object.__getattribute__(cls, attr)
            if hasattr(val, '__get__'):
                result = val.__get__(cls, type(cls))
            else:
                result = val
        return result
def test___WALTER_2015___RoboAI___MidTerm_Q2():
    """test: WALTER (2015) "Planning, Learning & Estimation in Robotics & A.I.": Mid-Term Exam, Question 2"""

    p_B = PMF(dict.fromkeys(('B',)),
              {fdict(B=0): .7,
               fdict(B=1): .3})
    p_E = PMF(dict.fromkeys(('E',)),
              {fdict(E=0): .5,
               fdict(E=1): .5})
    p_A_on_E = PMF(dict.fromkeys(('A', 'E')),
                   {fdict(E=0, A=0): .9,
                    fdict(E=0, A=1): .1,
                    fdict(E=1, A=0): .1,
                    fdict(E=1, A=1): .9},
                   cond=dict(E=None))
    p_C_on_A_B = PMF(dict.fromkeys(('A', 'B', 'C')),
                     {fdict(A=0, B=0, C=0): .9,
                      fdict(A=0, B=0, C=1): .1,
                      fdict(A=0, B=1, C=0): .2,
                      fdict(A=0, B=1, C=1): .8,
                      fdict(A=1, B=0, C=0): .3,
                      fdict(A=1, B=0, C=1): .7,
                      fdict(A=1, B=1, C=0): .1,
                      fdict(A=1, B=1, C=1): .9},
                     cond=dict(A=None, B=None))
    p_D_on_C = PMF(dict.fromkeys(('C', 'D')),
                   {fdict(C=0, D=0): .6,
                    fdict(C=0, D=1): .4,
                    fdict(C=1, D=0): .4,
                    fdict(C=1, D=1): .6},
                   cond=dict(C=None))

    p_C_equal_1_on_A_equal_1 = (p_B * p_C_on_A_B.at(A=1, C=1)).marg('B')
    p_C_equal_1_on_A_equal_1.pprint()
    p_C_equal_1_on_A_equal_1___answer = PMF(dict.fromkeys(('A', 'C')),
                                            {fdict(C=1): .76},
                                            cond=dict(A=1),
                                            scope=dict(C=1))
    p_C_equal_1_on_A_equal_1___check = p_C_equal_1_on_A_equal_1.allclose(p_C_equal_1_on_A_equal_1___answer)

    p_A = (p_E * p_A_on_E).marg('E')
    p_A.pprint()
    p_A___answer = PMF(dict.fromkeys(('A',)),
                       {fdict(A=0): .5,
                        fdict(A=1): .5})
    p_A___check = p_A.allclose(p_A___answer)

    p_C_on_B_equal_1 = (p_A * p_C_on_A_B.at(B=1)).marg('A')
    p_C_on_B_equal_1.pprint()
    p_C_on_B_equal_1___answer = PMF(dict.fromkeys(('B', 'C')),
                                    {fdict(C=0): .15,
                                     fdict(C=1): .85},
                                    cond=dict(B=1))
    p_C_on_B_equal_1___check = p_C_on_B_equal_1.allclose(p_C_on_B_equal_1___answer)

    p_D_equal_1_on_B_equal_1 = (p_C_on_B_equal_1 * p_D_on_C.at(D=1)).marg('C')
    p_D_equal_1_on_B_equal_1.pprint()
    p_D_equal_1_on_B_equal_1___answer = PMF(dict.fromkeys(('B', 'D')),
                                            {fdict(D=1): .57},
                                            cond=dict(B=1),
                                            scope=dict(D=1))
    p_D_equal_1_on_B_equal_1___check = p_D_equal_1_on_B_equal_1.allclose(p_D_equal_1_on_B_equal_1___answer)

    p_C = (p_A * p_B * p_C_on_A_B).marg('A', 'B')
    p_C.pprint()
    p_C___answer = PMF(dict.fromkeys(('C',)),
                       {fdict(C=0): .9 * .5 * .7 + .2 * .5 * .3 + .3 * .5 * .7 + .1 * .5 * .3,
                        fdict(C=1): .1 * .5 * .7 + .8 * .5 * .3 + .7 * .5 * .7 + .9 * .5 * .3})
    p_C___check = p_C.allclose(p_C___answer)

    p_D_equal_1 = (p_C * p_D_on_C.at(D=1)).marg('C')
    p_D_equal_1.pprint()
    p_D_equal_1___answer = PMF(dict.fromkeys(('D',)),
                               {fdict(D=1): .4 * (.9 * .5 * .7 + .2 * .5 * .3 + .3 * .5 * .7 + .1 * .5 * .3) +
                                            .6 * (.1 * .5 * .7 + .8 * .5 * .3 + .7 * .5 * .7 + .9 * .5 * .3)},
                               scope=dict(D=1))
    p_D_equal_1___check = p_D_equal_1.allclose(p_D_equal_1___answer)

    p_A_C_on_B = p_A * p_C_on_A_B
    p_C_on_B = p_A_C_on_B.marg('A')
    p_B_C_D = p_B * p_C_on_B * p_D_on_C
    p_B_D = p_B_C_D.marg('C')
    p_B_equal_1_on_D_equal_1 = p_B_D.cond(D=1).norm().at(B=1)
    p_B_equal_1_on_D_equal_1.pprint()
    p_B_equal_1_on_D_equal_1___answer = PMF(dict.fromkeys(('B', 'D')),
                                            {fdict(B=1): .337},
                                            cond=dict(D=1),
                                            scope=dict(B=1))
    p_B_equal_1_on_D_equal_1___check = p_B_equal_1_on_D_equal_1.allclose(p_B_equal_1_on_D_equal_1___answer, atol=1e-3)

    assert p_C_equal_1_on_A_equal_1___check & p_A___check & p_C_on_B_equal_1___check &\
        p_D_equal_1_on_B_equal_1___check & p_C___check & p_D_equal_1___check & p_B_equal_1_on_D_equal_1___check
def test___WALTER_2015___RoboAI___ProbSet1_Q4():
    """test: WALTER (2015) "Planning, Learning & Estimation in Robotics & A.I.": Problem Set 1, Question 4"""

    # Number of Time Periods
    T = 3

    state_prior = PMF(dict.fromkeys((('X', 0),)),
                      {fdict({('X', 0): 0}): .5,
                       fdict({('X', 0): 1}): .5})
    state_transition_template = PMF(dict.fromkeys((('X', -1), ('X', 0))),
                                    {fdict({('X', -1): 0, ('X', 0): 0}): .6,
                                     fdict({('X', -1): 0, ('X', 0): 1}): .4,
                                     fdict({('X', -1): 1, ('X', 0): 0}): .3,
                                     fdict({('X', -1): 1, ('X', 0): 1}): .7},
                                    cond={('X', -1): None})
    observation_template = PMF(dict.fromkeys((('X', 0), ('Z', 0))),
                               {fdict({('X', 0): 0, ('Z', 0): 0}): .8,
                                fdict({('X', 0): 0, ('Z', 0): 1}): .2,
                                fdict({('X', 0): 1, ('Z', 0): 0}): .2,
                                fdict({('X', 0): 1, ('Z', 0): 1}): .8},
                               cond={('X', 0): None})
    hmm = HMM('X', 'Z', state_prior, state_transition_template, observation_template)

    # Set up Probability Factors / Joint Probability Distributions
    print('\nPROBLEM SETUPS:\n')

    print('Prob(X_0) =')
    hmm.state_prior_pdf.pprint()

    for t in range(1, T + 1):
        print('Prob(X_%i | X_%i) =' % (t, t - 1))
        hmm.transition_pdf(t).pprint()

    for t in range(T + 1):
        print('Prob(Z_%i | X_%i) =' % (t, t))
        hmm.observation_pdf(t).pprint()

    all_z = {0: 0, 1: 0, 2: 1, 3: 0}
    print('actual z values =\n', all_z)

    # PART (A): FORWARD-BACKWARD ALGORITHM
    print('\nFORWARD-BACKWARD ALGORITHM:\n')

    print('"Forward" Probabilities:\n')
    forward = hmm.forward_pdf(range(T + 1), all_z)

    for t in range(T + 1):
        print('Prob(X_%i, z up to z_%i) =' % (t, t))
        forward[t].pprint()

    alpha_0 = PMF(dict.fromkeys((('X', 0), ('Z', 0))),
                  {fdict({('X', 0): 0, ('Z', 0): 0}): .4,
                   fdict({('X', 0): 1, ('Z', 0): 0}): .1},
                  scope={('Z', 0): 0})
    forward_0___check = forward[0].allclose(alpha_0)

    alpha_1 = PMF(dict.fromkeys((('X', 1), ('Z', 0), ('Z', 1))),
                  {fdict({('X', 1): 0, ('Z', 0): 0, ('Z', 1): 0}): .216,
                   fdict({('X', 1): 1, ('Z', 0): 0, ('Z', 1): 0}): .046},
                  scope={('Z', 0): 0, ('Z', 1): 0})
    forward_1___check = forward[1].allclose(alpha_1)

    alpha_2 = PMF(dict.fromkeys((('X', 2), ('Z', 0), ('Z', 1), ('Z', 2))),
                  {fdict({('X', 2): 0, ('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1}): .0287,
                   fdict({('X', 2): 1, ('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1}): .0949},
                  scope={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1})
    forward_2___check = forward[2].allclose(alpha_2, atol=1e-3)

    alpha_3 = PMF(dict.fromkeys((('X', 3), ('Z', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                  {fdict({('X', 3): 0, ('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}): .0365,
                   fdict({('X', 3): 1, ('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}): .0156},
                  scope={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0})
    forward_3___check = forward[3].allclose(alpha_3, atol=1e-2)

    print('"Backward" Probabilities:\n')
    backward = hmm.backward_factor(range(T + 1), all_z)

    for t in reversed(range(T + 1)):   # Recursively compute Backward factors
        print('Prob(z_%i to %i | X_%i) =' % (t + 1, T, t))
        backward[t].pprint()

    beta_3 = PMF(dict.fromkeys((('X', 3),)),
                 {fdict({('X', 3): 0}): 1.,
                  fdict({('X', 3): 1}): 1.},
                 cond={('X', 3): None})
    backward_3___check = backward[3].allclose(beta_3)

    beta_2 = PMF(dict.fromkeys((('X', 2), ('Z', 3))),
                 {fdict({('X', 2): 0, ('Z', 3): 0}): .56,
                  fdict({('X', 2): 1, ('Z', 3): 0}): .38},
                 cond={('X', 2): None},
                 scope={('Z', 3): 0})
    backward_2___check = backward[2].allclose(beta_2)

    beta_1 = PMF(dict.fromkeys((('X', 1), ('Z', 2), ('Z', 3))),
                 {fdict({('X', 1): 0, ('Z', 2): 1, ('Z', 3): 0}): .1888,
                  fdict({('X', 1): 1, ('Z', 2): 1, ('Z', 3): 0}): .2464},
                 cond={('X', 1): None},
                 scope={('Z', 2): 1, ('Z', 3): 0})
    backward_1___check = backward[1].allclose(beta_1)

    beta_0 = PMF(dict.fromkeys((('X', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                 {fdict({('X', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}): .1103,
                  fdict({('X', 0): 1, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}): .0798},
                 cond={('X', 0): None},
                 scope={('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0})
    backward_0___check = backward[0].allclose(beta_0, atol=1e-3)

    print('Probability of each X conditional on all z values:\n')
    infer_state = hmm.infer_state(range(T + 1), all_z)
    for t in range(4):
        print('Prob(X_%i | all z) =' % t)
        infer_state[t].pprint()

    infer_0 = PMF(dict.fromkeys((('X', 0), ('Z', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                  {fdict({('X', 0): 0}): .4 * .1103,
                   fdict({('X', 0): 1}): .1 * .0798},
                  cond={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}).norm()
    infer_0.pprint()
    infer_0___check = infer_state[0].allclose(infer_0, atol=1e-3)

    infer_1 = PMF(dict.fromkeys((('X', 1), ('Z', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                  {fdict({('X', 1): 0}): .216 * .1888,
                   fdict({('X', 1): 1}): .046 * .2464},
                  cond={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}).norm()
    infer_1.pprint()
    infer_1___check = infer_state[1].allclose(infer_1)

    infer_2 = PMF(dict.fromkeys((('X', 2), ('Z', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                  {fdict({('X', 2): 0}): .0287 * .56,
                   fdict({('X', 2): 1}): .0949 * .38},
                  cond={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}).norm()
    infer_2.pprint()
    infer_2___check = infer_state[2].allclose(infer_2, atol=1e-3)

    infer_3 = PMF(dict.fromkeys((('X', 3), ('Z', 0), ('Z', 1), ('Z', 2), ('Z', 3))),
                  {fdict({('X', 3): 0}): .0365,
                   fdict({('X', 3): 1}): .0156},
                  cond={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0}).norm()
    infer_3.pprint()
    infer_3___check = infer_state[3].allclose(infer_3, atol=1e-2)

    print('MAP of each X:\n')
    for t in range(T + 1):
        print('MAP Prob(X_%i | all z) =' % t)
        infer_state[t].max().pprint()

    # PART (B): VITERBI ALGORITHM
    print('\nVITERBI ALGORITHM:\n')

    all_z = [[0]]
    all_z += [all_z[0] + [0]]
    all_z += [all_z[1] + [1]]
    all_z += [all_z[2] + [0]]
    map_joint_distributions = []
    for t in range(T + 1):
        print('Most Likely Joint Distribution with actual z values up to z_%i:' % t)
        map_joint_distributions += [hmm.max_a_posteriori_joint_distributions(all_z[t])]
        map_joint_distributions[t].pprint()

    map_0 = PMF(dict.fromkeys((('X', 0), ('Z', 0))),
                {fdict({('X', 0): 0, ('Z', 0): 0}): .4},
                scope={('Z', 0): 0})
    map_0___check = map_joint_distributions[0].allclose(map_0)

    map_1 = PMF(dict.fromkeys((('X', 0), ('Z', 0), ('X', 1), ('Z', 1))),
                {fdict({('X', 0): 0, ('Z', 0): 0, ('X', 1): 0, ('Z', 1): 0}): .192},
                scope={('Z', 0): 0, ('Z', 1): 0})
    map_1___check = map_joint_distributions[1].allclose(map_1)

    map_2 = PMF(dict.fromkeys((('X', 0), ('Z', 0), ('X', 1), ('Z', 1), ('X', 2), ('Z', 2))),
                {fdict({('X', 0): 0, ('Z', 0): 0, ('X', 1): 0, ('Z', 1): 0, ('X', 2): 1, ('Z', 2): 1}): .0614},
                scope={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1})
    map_2___check = map_joint_distributions[2].allclose(map_2, atol=1e-3)

    map_3 = PMF(dict.fromkeys((('X', 0), ('Z', 0), ('X', 1), ('Z', 1), ('X', 2), ('Z', 2), ('X', 3), ('Z', 3))),
                {fdict({('X', 0): 0, ('Z', 0): 0, ('X', 1): 0, ('Z', 1): 0, ('X', 2): 1, ('Z', 2): 1,
                                      ('X', 3): 0, ('Z', 3): 0}): .0147},
                scope={('Z', 0): 0, ('Z', 1): 0, ('Z', 2): 1, ('Z', 3): 0})
    map_3___check = map_joint_distributions[3].allclose(map_3, atol=1e-2)

    map_state_sequence = hmm.max_a_posteriori_state_sequence(all_z[3])
    pprint(map_state_sequence)
    map_state_sequence___answer = [0, 0, 1, 0]
    map_state_sequence___check = map_state_sequence == map_state_sequence___answer

    assert forward_0___check & forward_1___check & forward_2___check & forward_3___check &\
        backward_0___check & backward_1___check & backward_2___check & backward_3___check &\
        infer_0___check & infer_1___check & infer_2___check & infer_3___check &\
        map_0___check & map_1___check & map_2___check & map_3___check & map_state_sequence___check
Example #19
0
    def test_len(self):
        fd1 = fdict(a=1, b=2)
        T.assert_equal(len(fd1), 2)

        fd2 = fdict(c=3, **fd1)
        T.assert_equal(len(fd2), 3)
def test___WALTER_2015___RoboAI___ProbSet1_Q2(alpha=.6):   # Symbol('alpha')
    """test: WALTER (2015) "Planning, Learning & Estimation in Robotics & A.I.": Problem Set 1, Question 2"""
    p_S0_S1 = PMF(dict.fromkeys(('S0', 'S1')),
                  {fdict(S0=0, S1=0): .9,
                   fdict(S0=0, S1=1): .1,
                   fdict(S0=1, S1=0): .1,
                   fdict(S0=1, S1=1): .9})
    p_S1_S2 = PMF(dict.fromkeys(('S1', 'S2')),
                  {fdict(S1=0, S2=0): alpha,
                   fdict(S1=0, S2=1): 1. - alpha,
                   fdict(S1=1, S2=0): 1. - alpha,
                   fdict(S1=1, S2=1): alpha})
    p_S2_S3 = PMF(dict.fromkeys(('S2', 'S3')),
                  {fdict(S2=0, S3=0): alpha,
                   fdict(S2=0, S3=1): 1. - alpha,
                   fdict(S2=1, S3=0): 1. - alpha,
                   fdict(S2=1, S3=1): alpha})
    p_S3_S4 = PMF(dict.fromkeys(('S3', 'S4')),
                  {fdict(S3=0, S4=0): .9,
                   fdict(S3=0, S4=1): .1,
                   fdict(S3=1, S4=0): .1,
                   fdict(S3=1, S4=1): .9})

    p_S1_on_S0_equal_1 = p_S0_S1.cond(S0=1)
    p_S3_on_S4_equal_0 = p_S3_S4.cond(S4=0)
    p_S1_on_S0_equal_1_and_S4_equal_0 = (p_S1_on_S0_equal_1 * p_S1_S2 * p_S2_S3 * p_S3_on_S4_equal_0)\
                                         .marg('S2', 'S3').norm()
    p_S1_on_S0_equal_1_and_S4_equal_0.pprint()

    lambda_0 = lambda a: .09 * (2 * a ** 2 - 2 * a + 1) + .02 * a * (1. - a)
    lambda_1 = lambda a: .09 * (2 * a ** 2 - 2 * a + 1) + 1.62 * a * (1. - a)
    p_S1_on_S0_equal_1_and_S4_equal_0___answer = PMF(dict.fromkeys(('S0', 'S1', 'S4')),
                                                     {fdict(S1=0): lambda_0(alpha),
                                                      fdict(S1=1): lambda_1(alpha)},
                                                     cond=dict(S0=1, S4=0)).norm()

    assert p_S1_on_S0_equal_1_and_S4_equal_0.allclose(p_S1_on_S0_equal_1_and_S4_equal_0___answer)
def train_hmm(training_data_sequences):

    state_prior_counts = {}
    observation_counts = {}
    transition_counts = {}

    for i in range(len(training_data_sequences)):
        data_sequence = training_data_sequences[i]
        xy = [data_sequence.iloc[0]['xy']]
        ob = [data_sequence.iloc[0]['ob']]
        if fdict({('xy', 0): xy[0]}) in state_prior_counts:
            state_prior_counts[fdict({('xy', 0): xy[0]})] += 1.
        else:
            state_prior_counts[fdict({('xy', 0): xy[0]})] = 1.
        if fdict({('xy', 0): xy[0], ('ob', 0): ob[0]}) in observation_counts:
            observation_counts[fdict({('xy', 0): xy[0], ('ob', 0): ob[0]})] += 1.
        else:
            observation_counts[fdict({('xy', 0): xy[0], ('ob', 0): ob[0]})] = 1.
        for t in range(1, len(data_sequence)):
            xy += [data_sequence.iloc[t]['xy']]
            ob += [data_sequence.iloc[t]['ob']]
            if fdict({('xy', -1): xy[t - 1], ('xy', 0): xy[t]}) in transition_counts:
                transition_counts[fdict({('xy', -1): xy[t - 1], ('xy', 0): xy[t]})] += 1.
            else:
                transition_counts[fdict({('xy', -1): xy[t - 1], ('xy', 0): xy[t]})] = 1.
            if fdict({('xy', 0): xy[t], ('ob', 0): ob[t]}) in observation_counts:
                observation_counts[fdict({('xy', 0): xy[t], ('ob', 0): ob[t]})] += 1.
            else:
                observation_counts[fdict({('xy', 0): xy[t], ('ob', 0): ob[t]})] = 1.

    state_prior_minus_log_counts = {k: -log(v) for k, v in state_prior_counts.items()}
    transition_minus_log_counts = {k: -log(v) for k, v in transition_counts.items()}
    observation_minus_log_counts = {k: -log(v) for k, v in observation_counts.items()}

    state_prior = PMF(dict.fromkeys((('xy', 0), ('ob', 0))),
                      state_prior_minus_log_counts).norm()
    transition_template = PMF(dict.fromkeys((('xy', -1), ('xy', 0))),
                              transition_minus_log_counts,
                              conditions={('xy', -1): None}).norm()
    observation_template = PMF(dict.fromkeys((('xy', 0), ('ob', 0))),
                               observation_minus_log_counts,
                               conditions={('xy', 0): None}).norm()

    return state_prior, transition_template, observation_template