def apply(*given): x, y = process_assumptions(*given) n, d = x.shape t = Symbol.t(integer=True, domain=[0, n - 1]) i = Symbol.i(integer=True) joint_probability = P(x[:t + 1], y[:t + 1]) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) y_given_x_probability = P(y | x) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) z = Symbol.z(shape=(n, d), definition=LAMBDA[y[t], t](Piecewise( (Sum[y[0:t]](sympy.E**-s[t]), t > 0), (sympy.E**-s[t], True)))) # assert z.is_extended_positive x_quote = Symbol.x_quote(shape=(n, d), definition=-LAMBDA[t](sympy.log(z[t]))) # assert x_quote.is_real return Equality(x_quote[t + 1], -log(Sum(exp(-x_quote[t] - G))) + x[t + 1], given=given), \ Equality(-log(y_given_x_probability), log(Sum(exp(-x_quote[n - 1]))) + s[n - 1], given=given)
def apply(*given): x, y = process_assumptions(*given) n, d = x.shape t = Symbol.t(integer=True, domain=[0, n - 1]) i = Symbol.i(integer=True) joint_probability_t = P(x[:t + 1], y[:t + 1]) joint_probability = P(x, y) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability_t))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) x_quote = Symbol.x_quote(shape=(n, d), definition=LAMBDA[y[t], t](Piecewise( (MIN[y[0:t]](s[t]), t > 0), (s[0], True)))) assert x_quote.is_real return Equality(x_quote[t + 1], x[t + 1] + MIN(x_quote[t] + G), given=given), \ Equality(MAX[y](joint_probability), exp(-MIN(x_quote[n - 1])), given=given)
def prove(Eq): # d is the number of output labels # oo is the length of the sequence d = Symbol.d(integer=True, positive=True) n = Symbol.n(integer=True, positive=True) x = Symbol.x(shape=(n, d), real=True, random=True, given=True) y = Symbol.y(shape=(n, ), integer=True, domain=[0, d - 1], random=True, given=True) i = Symbol.i(integer=True) t = Symbol.t(integer=True, domain=[0, n]) joint_probability_t = P(x[:t + 1], y[:t + 1]) emission_probability = P(x[i] | y[i]) transition_probability = P(y[i] | y[i - 1]) given = Equality( joint_probability_t, P(x[0] | y[0]) * P(y[0]) * Product[i:1:t](transition_probability * emission_probability)) y = pspace(y).symbol G = Symbol.G(shape=(d, d), definition=LAMBDA[y[i - 1], y[i]](-sympy.log(transition_probability))) s = Symbol.s(shape=(n, ), definition=LAMBDA[t](-log(joint_probability_t))) x = Symbol.x(shape=(n, d), definition=LAMBDA[y[i], i](-sympy.log(emission_probability))) Eq.s_definition, Eq.G_definition, Eq.x_definition, Eq.given, Eq.logits_recursion = apply( G, x, s, given=given) Eq << Eq.s_definition.this.rhs.subs(Eq.given) Eq << Eq[-1].this.rhs.args[1].as_Add() Eq << Eq[-1].subs(Eq.x_definition.subs(i, 0).reversed) Eq << Eq[-1].this.rhs.args[-1].args[1].as_Add() Eq << Eq[-1].this.rhs.args[-1].args[1].function.as_Add() Eq << Eq[-1].this.rhs.args[-1].args[1].as_two_terms() Eq << Eq[-1].subs(Eq.x_definition.reversed).subs(Eq.G_definition.reversed) Eq << Eq[-1].this.rhs.args[-1].bisect({0}) Eq << Eq[-1].subs(t, t + 1) - Eq[-1] s = Eq.s_definition.lhs.base Eq << Eq[-1].this.rhs.simplify() + s[t]