def test_function(self): with self.compiler.graph.as_default(): shape_scope = { 'mu/1': TensorFluentShape([24], batch=False), 'sigma/1': TensorFluentShape([24], batch=False) } scope = { 'mu/1': TensorFluent(tf.zeros([24]), scope=['?x'], batch=False), 'sigma/1': TensorFluent(tf.ones([24]), scope=['?x'], batch=False) } noise1 = get_reparameterization(self.exp_2, scope=shape_scope) self._test_reparameterization_dist(noise1, []) self._test_reparameterized_expression(self.exp_2, scope=scope, noise=noise1, name='noise1') noise2 = get_reparameterization(self.exp_z, scope=shape_scope) self._test_reparameterization_dist(noise2, [('Normal', [1])]) self._test_reparameterized_expression(self.exp_z, scope=scope, noise=noise2, name='noise2') noise3 = get_reparameterization(self.exp_x1, scope=shape_scope) self._test_reparameterization_dist(noise3, [('Normal', [24])]) self._test_reparameterized_expression(self.exp_x1, scope=scope, noise=noise3, name='noise3') noise4 = get_reparameterization(self.y1, scope=shape_scope) self._test_reparameterization_dist(noise4, [('Normal', [1]), ('Normal', [1])]) self._test_reparameterized_expression(self.y1, scope=scope, noise=noise4, name='noise4') noise5 = get_reparameterization(self.y2, scope=shape_scope) self._test_reparameterization_dist(noise5, [('Normal', [1]), ('Normal', [24])]) self._test_reparameterized_expression(self.y2, scope=scope, noise=noise5, name='noise5') noise6 = get_reparameterization(self.y3, scope=shape_scope) self._test_reparameterization_dist(noise6, [('Normal', [24]), ('Normal', [24])]) self._test_reparameterized_expression(self.y3, scope=scope, noise=noise6, name='noise6')
def _broadcast(shape1: TensorFluentShape, shape2: TensorFluentShape) -> TensorFluentShape: s1, s2 = TensorFluentShape.broadcast(shape1, shape2) s1 = s1 if s1 is not None else shape1.as_list() s2 = s2 if s2 is not None else shape2.as_list() x1, x2 = np.zeros(s1), np.zeros(s2) y = np.broadcast(x1, x2) return TensorFluentShape(y.shape, batch=(shape1.batch or shape2.batch))
def __init__(self, tensor: tf.Tensor, scope: List[str], batch: bool = False) -> None: self.tensor = tensor self.scope = TensorFluentScope(scope) self.shape = TensorFluentShape(tensor.shape, batch)
def test_gamma(self): # rainfall(?r) = Gamma(RAIN_SHAPE(?r), RAIN_SCALE(?r)); with self.compiler.graph.as_default(): shape_scope = { 'shape/1': TensorFluentShape((32, 8), batch=True), 'scale/1': TensorFluentShape((32, 8), batch=True) } scope = { 'shape/1': TensorFluent(tf.ones((32, 8)), scope=['?r'], batch=True), 'scale/1': TensorFluent(tf.ones((32, 8)), scope=['?r'], batch=True) } noise1 = get_reparameterization(self.gamma1, scope=shape_scope) self._test_reparameterization_dist(noise1, [('Gamma', [32, 8])]) self._test_reparameterized_expression(self.gamma1, scope=scope, noise=noise1, name='noise1')
def test_arithmetic(self): with self.compiler.graph.as_default(): shape_scope = { 'mu/1': TensorFluentShape([32], batch=False), 'sigma/1': TensorFluentShape([32], batch=False) } scope = { 'mu/1': TensorFluent(tf.zeros([32]), scope=['?x'], batch=False), 'sigma/1': TensorFluent(tf.ones([32]), scope=['?x'], batch=False) } noise1 = get_reparameterization(self.two, scope={}) self._test_reparameterization_dist(noise1, []) self._test_reparameterized_expression(self.two, scope={}, noise=noise1, name='noise1') noise2 = get_reparameterization(self.z_times_z, scope={}) self._test_reparameterization_dist(noise2, [('Normal', [1]), ('Normal', [1])]) self._test_reparameterized_expression(self.z_times_z, scope={}, noise=noise2, name='noise2') noise3 = get_reparameterization(self.x2_times_x2, scope=shape_scope) self._test_reparameterization_dist(noise3, [('Normal', [32]), ('Normal', [32])]) self._test_reparameterized_expression(self.x2_times_x2, scope=scope, noise=noise3, name='noise3') noise4 = get_reparameterization(self.mu_plus_z, scope=shape_scope) self._test_reparameterization_dist(noise4, [('Normal', [1])]) self._test_reparameterized_expression(self.mu_plus_z, scope=scope, noise=noise4, name='noise4') noise5 = get_reparameterization(self.z_plus_mu, scope=shape_scope) self._test_reparameterization_dist(noise5, [('Normal', [1])]) self._test_reparameterized_expression(self.z_plus_mu, scope=scope, noise=noise5, name='noise5') noise6 = get_reparameterization(self.mu_plus_x2, scope=shape_scope) self._test_reparameterization_dist(noise6, [('Normal', [32])]) self._test_reparameterized_expression(self.mu_plus_x2, scope=scope, noise=noise6, name='noise6') noise7 = get_reparameterization(self.x2_plus_mu, scope=shape_scope) self._test_reparameterization_dist(noise7, [('Normal', [32])]) self._test_reparameterized_expression(self.x2_plus_mu, scope=scope, noise=noise7, name='noise7') noise8 = get_reparameterization(self.x1_plus_z, scope=shape_scope) self._test_reparameterization_dist(noise8, [('Normal', [32]), ('Normal', [1])]) self._test_reparameterized_expression(self.x1_plus_z, scope=scope, noise=noise8, name='noise8') noise9 = get_reparameterization(self.z_plus_x1, scope=shape_scope) self._test_reparameterization_dist(noise9, [('Normal', [1]), ('Normal', [32])]) self._test_reparameterized_expression(self.z_plus_x1, scope=scope, noise=noise9, name='noise9')
def test_multivariate_normal(self): with self.compiler.graph.as_default(): shape_scope = { 'mu/1': TensorFluentShape([32], batch=False), 'sigma/1': TensorFluentShape([32], batch=False) } scope = { 'mu/1': TensorFluent(tf.zeros([32]), scope=['?x'], batch=False), 'sigma/1': TensorFluent(tf.ones([32]), scope=['?x'], batch=False) } noise1 = get_reparameterization(self.x1, scope=shape_scope) self._test_reparameterization_dist(noise1, [('Normal', [32])]) self._test_reparameterized_expression(self.x1, scope=scope, noise=noise1, name='noise1') noise2 = get_reparameterization(self.x2, scope=shape_scope) self._test_reparameterization_dist(noise2, [('Normal', [32])]) self._test_reparameterized_expression(self.x2, scope=scope, noise=noise2, name='noise2') noise3 = get_reparameterization(self.x3, scope=shape_scope) self._test_reparameterization_dist(noise3, [('Normal', [32])]) self._test_reparameterized_expression(self.x3, scope=scope, noise=noise3, name='noise3') noise4 = get_reparameterization(self.x4, scope=shape_scope) self._test_reparameterization_dist(noise4, [('Normal', [1]), ('Normal', [1])]) self._test_reparameterized_expression(self.x4, scope=scope, noise=noise4, name='noise4') noise5 = get_reparameterization(self.x5, scope=shape_scope) self._test_reparameterization_dist(noise5, [('Normal', [32]), ('Normal', [32])]) self._test_reparameterized_expression(self.x5, scope=scope, noise=noise5, name='noise5') noise6 = get_reparameterization(self.x6, scope=shape_scope) self._test_reparameterization_dist(noise6, [('Normal', [32]), ('Normal', [32])]) self._test_reparameterized_expression(self.x6, scope=scope, noise=noise6, name='noise6') noise7 = get_reparameterization(self.x7, scope=shape_scope) self._test_reparameterization_dist(noise7, [('Normal', [1]), ('Normal', [1]), ('Normal', [1])]) self._test_reparameterized_expression(self.x7, scope=scope, noise=noise7, name='noise7') noise8 = get_reparameterization(self.x8, scope=shape_scope) self._test_reparameterization_dist(noise8, [('Normal', [1]), ('Normal', [1]), ('Normal', [32])]) self._test_reparameterized_expression(self.x8, scope=scope, noise=noise8, name='noise8') noise9 = get_reparameterization(self.x9, scope=shape_scope) self._test_reparameterization_dist(noise9, [('Normal', [32]), ('Normal', [1]), ('Normal', [1]), ('Normal', [32])]) self._test_reparameterized_expression(self.x9, scope=scope, noise=noise9, name='noise9')
def test_exponential(self): # rainfall(?r) = Exponential(RAIN_RATE(?r)); with self.compiler.graph.as_default(): shape_scope = { 'rate/1': TensorFluentShape((32, 8), batch=True) } scope = { 'rate/1': TensorFluent(tf.ones((32, 8)), scope=['?r'], batch=True) } noise1 = get_reparameterization(self.exp1, scope=shape_scope) self._test_reparameterization_dist(noise1, [('Uniform', [32, 8])]) self._test_reparameterized_expression(self.exp1, scope=scope, noise=noise1, name='noise1')
def test_batch_normal(self): with self.compiler.graph.as_default(): shape_scope = { 'mu/1': TensorFluentShape((64, 16), batch=True), 'sigma/1': TensorFluentShape((64, 16), batch=True) } scope = { 'mu/1': TensorFluent(tf.zeros([64, 16]), scope=['?x'], batch=True), 'sigma/1': TensorFluent(tf.ones([64, 16]), scope=['?x'], batch=True) } noise1 = get_reparameterization(self.x1, scope=shape_scope) self._test_reparameterization_dist(noise1, [('Normal', [64, 16])]) self._test_reparameterized_expression(self.x1, scope=scope, noise=noise1, name='noise1') noise2 = get_reparameterization(self.x2, scope=shape_scope) self._test_reparameterization_dist(noise2, [('Normal', [64, 16])]) self._test_reparameterized_expression(self.x2, scope=scope, noise=noise2, name='noise2') noise3 = get_reparameterization(self.x3, scope=shape_scope) self._test_reparameterization_dist(noise3, [('Normal', [64, 16])]) self._test_reparameterized_expression(self.x3, scope=scope, noise=noise3, name='noise3')
def _binary_op(cls, x: 'TensorFluent', y: 'TensorFluent', op: Callable[[tf.Tensor, tf.Tensor], tf.Tensor], dtype: tf.DType) -> 'TensorFluent': '''Returns a TensorFluent for the binary `op` applied to fluents `x` and `y`. Args: x: The first operand. y: The second operand. op: The binary operator. dtype: The output's data type. Returns: A TensorFluent wrapping the binary operator's output. ''' # scope s1 = x.scope.as_list() s2 = y.scope.as_list() scope, perm1, perm2 = TensorFluentScope.broadcast(s1, s2) if x.batch and perm1 != []: perm1 = [0] + [p+1 for p in perm1] if y.batch and perm2 != []: perm2 = [0] + [p+1 for p in perm2] x = x.transpose(perm1) y = y.transpose(perm2) # shape reshape1, reshape2 = TensorFluentShape.broadcast(x.shape, y.shape) if reshape1 is not None: x = x.reshape(reshape1) if reshape2 is not None: y = y.reshape(reshape2) # dtype x = x.cast(dtype) y = y.cast(dtype) # operation t = op(x.tensor, y.tensor) # batch batch = x.batch or y.batch return TensorFluent(t, scope, batch=batch)
def test_broadcast(self): tests = [ (TensorFluentShape([], False), TensorFluentShape([], False), None, None), (TensorFluentShape([8], False), TensorFluentShape([], False), None, None), (TensorFluentShape([], False), TensorFluentShape([8], False), None, None), (TensorFluentShape([8, 8], False), TensorFluentShape([8], False), None, None), (TensorFluentShape([8], False), TensorFluentShape([8, 8], False), None, None), (TensorFluentShape([100], True), TensorFluentShape([100], True), None, None), (TensorFluentShape([100, 8], True), TensorFluentShape([100], True), None, [100, 1]), (TensorFluentShape([100], True), TensorFluentShape([100, 8], True), [100, 1], None), (TensorFluentShape([100, 8, 8], True), TensorFluentShape([100], True), None, [100, 1, 1]), (TensorFluentShape([100], True), TensorFluentShape([100, 8, 8], True), [100, 1, 1], None), (TensorFluentShape([100, 8, 8], True), TensorFluentShape([100, 8], True), None, [100, 1, 8]), (TensorFluentShape([100, 8], True), TensorFluentShape([100, 8, 8], True), [100, 1, 8], None), (TensorFluentShape([100], True), TensorFluentShape([], False), None, None), (TensorFluentShape([], False), TensorFluentShape([], True), None, None), (TensorFluentShape([100], True), TensorFluentShape([], False), None, None), (TensorFluentShape([100], True), TensorFluentShape([8], False), [100, 1], None), (TensorFluentShape([8], False), TensorFluentShape([100], True), None, [100, 1]), (TensorFluentShape([100], True), TensorFluentShape([8, 7], False), [100, 1, 1], None), (TensorFluentShape([8, 7], False), TensorFluentShape([100], True), None, [100, 1, 1]), (TensorFluentShape([100, 8], True), TensorFluentShape([], False), None, None), (TensorFluentShape([], False), TensorFluentShape([100, 8], True), None, None), (TensorFluentShape([100, 8], True), TensorFluentShape([8], False), None, None), (TensorFluentShape([8], False), TensorFluentShape([100, 8], True), None, None), (TensorFluentShape([100, 8, 7], True), TensorFluentShape([7], False), None, [1, 7]), (TensorFluentShape([7], False), TensorFluentShape([100, 8, 7], True), [1, 7], None), (TensorFluentShape([100, 7, 8], True), TensorFluentShape([7, 8], False), None, None), (TensorFluentShape([7, 8], False), TensorFluentShape([100, 7, 8], True), None, None), (TensorFluentShape([8, 8], False), TensorFluentShape([100, 8], True), None, [100, 1, 8]), (TensorFluentShape([100, 8], True), TensorFluentShape([8, 8], False), [100, 1, 8], None), (TensorFluentShape([2, 2], False), TensorFluentShape([1, 2], True), None, [1, 1, 2]), (TensorFluentShape([1, 2], True), TensorFluentShape([2, 2], False), [1, 1, 2], None), ] for s1, s2, ss1, ss2 in tests: reshape1, reshape2 = TensorFluentShape.broadcast(s1, s2) if ss1 is None: self.assertIsNone(reshape1) else: self.assertListEqual(reshape1, ss1) if ss2 is None: self.assertIsNone(reshape2) else: self.assertListEqual(reshape2, ss2)
def _get_reparameterization(expr: Expression, scope: ShapeScope, noise: Noise) -> TensorFluentShape: etype = expr.etype args = expr.args if etype[0] == 'constant': return TensorFluentShape([1], batch=False) elif etype[0] == 'pvar': name = expr._pvar_to_name(args) if name not in scope: raise ValueError('Variable {} not in scope.'.format(name)) shape = scope[name] return shape elif etype[0] == 'randomvar': if etype[1] == 'Normal': mean_shape = _get_reparameterization(args[0], scope, noise) var_shape = _get_reparameterization(args[1], scope, noise) shape = _broadcast(mean_shape, var_shape) dist = tf.distributions.Normal(loc=0.0, scale=1.0) noise.append((dist, shape.as_list())) return shape elif etype[1] == 'Exponential': rate_shape = _get_reparameterization(args[0], scope, noise) dist = tf.distributions.Uniform(low=0.0, high=1.0) noise.append((dist, rate_shape.as_list())) return rate_shape elif etype[1] == 'Gamma': raise NotImplementedError elif etype[1] == 'Uniform': low_shape = _get_reparameterization(args[0], scope, noise) high_shape = _get_reparameterization(args[1], scope, noise) shape = _broadcast(low_shape, high_shape) dist = tf.distributions.Uniform(low=0.0, high=1.0) noise.append((dist, shape.as_list())) return shape elif etype[0] in ['arithmetic', 'boolean', 'relational']: op1_shape = _get_reparameterization(args[0], scope, noise) shape = op1_shape if len(args) > 1: op2_shape = _get_reparameterization(args[1], scope, noise) shape = _broadcast(op1_shape, op2_shape) return shape elif etype[0] == 'func': op1_shape = _get_reparameterization(args[0], scope, noise) shape = op1_shape if len(args) > 1: if len(args) == 2: op2_shape = _get_reparameterization(args[1], scope, noise) shape = _broadcast(op1_shape, op2_shape) else: raise ValueError('Invalid function:\n{}'.format(expr)) return shape elif etype[0] == 'control': if etype[1] == 'if': condition_shape = _get_reparameterization(args[0], scope, noise) true_case_shape = _get_reparameterization(args[1], scope, noise) false_case_shape = _get_reparameterization(args[2], scope, noise) shape = _broadcast(condition_shape, true_case_shape) shape = _broadcast(shape, false_case_shape) return shape else: raise ValueError( 'Invalid control flow expression:\n{}'.format(expr)) elif etype[0] == 'aggregation': return _get_reparameterization(args[-1], scope, noise) raise ValueError('Expression type unknown: {}'.format(etype))
def get_reparameterization_shape_scope(rddl: RDDL) -> ShapeScope: scope = { name: TensorFluentShape(size, batch=False) for name, (_, size) in rddl.fluent_table.items() } return scope