Example #1
0
    def test_compile_probabilistic_normal_random_variable(self):
        mean = Expression(('number', 0.0))
        var = Expression(('number', 1.0))
        normal = Expression(('randomvar', ('Normal', (mean, var))))

        expressions = [normal]
        self._test_random_variable_expressions(expressions)
Example #2
0
    def test_compile_probabilistic_gamma_random_variable(self):
        shape = Expression(('number', 5.0))
        scale = Expression(('number', 1.0))
        gamma = Expression(('randomvar', ('Gamma', (shape, scale))))

        expressions = [gamma]
        self._test_random_variable_expressions(expressions)
Example #3
0
    def _compile_pvariable_expression(self, expr: Expression,
                                      scope: Dict[str, TensorFluent],
                                      **kwargs) -> TensorFluent:
        '''Compile a pvariable expression `expr` into a TensorFluent
        in the given `scope`. The resulting TensorFluent will have
        batch dimension given by `batch_size`.

        Args:
            expr (:obj:`rddl2tf.expr.Expression`): A RDDL pvariable expression.
            scope (Dict[str, :obj:`rddl2tf.core.fluent.TensorFluent`]): A fluent scope.
            kwargs: Additional keyword arguments.

        Returns:
            :obj:`rddl2tf.core.fluent.TensorFluent`: The compiled expression as a TensorFluent.
        '''
        etype = expr.etype
        args = expr.args
        name = expr._pvar_to_name(args)
        if name not in scope:
            raise ValueError('Variable {} not in scope.'.format(name))
        fluent = scope[name]
        scope = args[1] if args[1] is not None else []
        if isinstance(fluent, TensorFluent):
            fluent = TensorFluent(fluent.tensor, scope, batch=fluent.batch)
        elif isinstance(fluent, tf.Tensor):
            fluent = TensorFluent(fluent, scope, batch=True)
        else:
            raise ValueError(
                'Variable in scope must be TensorFluent-like: {}'.format(
                    fluent))
        return fluent
Example #4
0
def test_gamma(compiler):
    if compiler.rddl.domain.name == "reservoir":
        shape_scope = compiler._get_reparameterization_shape_scope()

        shape = Expression(("pvar_expr", ("RAIN_SHAPE", ["?res"])))
        scale = Expression(("pvar_expr", ("RAIN_SCALE", ["?res"])))
        gamma = Expression(("randomvar", ("Gamma", (shape, scale))))

        noise_lst = compiler._get_expression_reparameterization(
            gamma, shape_scope)
        assert isinstance(noise_lst, list)
        assert len(noise_lst) == 1

        dist, shape = noise_lst[0]

        assert isinstance(dist, GAMMA)
        assert dist.batch_shape == (8, )
        assert dist.event_shape == ()
        assert shape == []
Example #5
0
 def p_expr(self, p):
     '''expr : pvar_expr
             | group_expr
             | function_expr
             | relational_expr
             | boolean_expr
             | quantifier_expr
             | numerical_expr
             | aggregation_expr
             | control_expr
             | randomvar_expr'''
     p[0] = Expression(p[1])
Example #6
0
import pytest
import tensorflow as tf

from pyrddl.expr import Expression
import rddlgym

from rddl2tf.compilers import ReparameterizationCompiler
from rddl2tf.core.fluent import TensorFluent
from rddl2tf.core.fluentshape import TensorFluentShape

NORMAL = tf.compat.v1.distributions.Normal
GAMMA = tf.compat.v1.distributions.Gamma
UNIFORM = tf.compat.v1.distributions.Uniform

ZERO = Expression(("number", 0.0))
ONE = Expression(("number", 1.0))
TWO = Expression(("+", (ONE, ONE)))

Z = Expression(("randomvar", ("Normal", (ZERO, ONE))))

MU = Expression(("pvar_expr", ("mu", ["?x"])))
SIGMA = Expression(("pvar_expr", ("sigma", ["?x"])))

X1 = Expression(("randomvar", ("Normal", (MU, ONE))))
X2 = Expression(("randomvar", ("Normal", (ZERO, SIGMA))))
X3 = Expression(("randomvar", ("Normal", (MU, SIGMA))))

X4 = Expression(("randomvar", ("Normal", (Z, ONE))))
X5 = Expression(("randomvar", ("Normal", (X1, ONE))))
X6 = Expression(("randomvar", ("Normal", (X1, SIGMA))))
    def _get_reparameterization(
        self, expr: Expression, scope: ShapeScope, noise: NoiseList
    ) -> 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 = self._get_reparameterization(args[0], scope, noise)
                var_shape = self._get_reparameterization(args[1], scope, noise)
                shape = ReparameterizationCompiler._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 = self._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":

                for fluent in self.rddl.get_dependencies(expr):
                    if fluent.is_state_fluent() or fluent.is_action_fluent():
                        raise ValueError(
                            f"Expression is not an exogenous event: {expr}"
                        )

                shape = []

                with self.graph.as_default():
                    scope = self._scope.non_fluents(self.non_fluents)
                    shape_fluent = self._compile_expression(args[0], scope, noise=None)
                    scale_fluent = self._compile_expression(args[1], scope, noise=None)
                    concentration = shape_fluent.tensor
                    rate = 1 / scale_fluent.tensor
                    dist = tf.distributions.Gamma(concentration, rate)

                noise.append((dist, shape))

                return shape

            elif etype[1] == "Uniform":
                low_shape = self._get_reparameterization(args[0], scope, noise)
                high_shape = self._get_reparameterization(args[1], scope, noise)
                shape = ReparameterizationCompiler._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 = self._get_reparameterization(args[0], scope, noise)
            shape = op1_shape
            if len(args) > 1:
                op2_shape = self._get_reparameterization(args[1], scope, noise)
                shape = ReparameterizationCompiler._broadcast(op1_shape, op2_shape)
            return shape
        elif etype[0] == "func":
            op1_shape = self._get_reparameterization(args[0], scope, noise)
            shape = op1_shape
            if len(args) > 1:
                if len(args) == 2:
                    op2_shape = self._get_reparameterization(args[1], scope, noise)
                    shape = ReparameterizationCompiler._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 = self._get_reparameterization(args[0], scope, noise)
                true_case_shape = self._get_reparameterization(args[1], scope, noise)
                false_case_shape = self._get_reparameterization(args[2], scope, noise)
                shape = ReparameterizationCompiler._broadcast(
                    condition_shape, true_case_shape
                )
                shape = ReparameterizationCompiler._broadcast(shape, false_case_shape)
                return shape
            else:
                raise ValueError("Invalid control flow expression:\n{}".format(expr))
        elif etype[0] == "aggregation":
            return self._get_reparameterization(args[-1], scope, noise)

        raise ValueError("Expression type unknown: {}".format(etype))
Example #8
0
 def name(self) -> str:
     '''Returns the CPF's pvariable name.'''
     return Expression._pvar_to_name(self.pvar[1])
Example #9
0
def test_get_dependencies(rddl):

    if rddl.domain.name == 'reservoir':
        shape = Expression(('pvar_expr', ('RAIN_SHAPE', ['?res'])))
        scale = Expression(('pvar_expr', ('RAIN_SCALE', ['?res'])))
        gamma = Expression(('randomvar', ('Gamma', (shape, scale))))

        deps = rddl.get_dependencies(gamma)
        assert isinstance(deps, set)
        assert len(deps) == 2
        deps = set(map(lambda fluent: str(fluent), deps))
        assert deps == {'RAIN_SCALE/1', 'RAIN_SHAPE/1'}

    elif rddl.domain.name == 'hvac_vav_fix':
        mean = Expression(('pvar_expr', ('TEMP_OUTSIDE_MEAN', ['?s'])))
        variance = Expression(('pvar_expr', ('TEMP_OUTSIDE_VARIANCE', ['?s'])))
        normal = Expression(('randomvar', ('Normal', (mean, variance))))

        deps = rddl.get_dependencies(normal)
        assert isinstance(deps, set)
        assert len(deps) == 2
        deps = set(map(lambda fluent: str(fluent), deps))
        assert deps == {'TEMP_OUTSIDE_MEAN/1', 'TEMP_OUTSIDE_VARIANCE/1'}

    elif rddl.domain.name == 'Navigation':
        location = Expression(('pvar_expr', ('location', ['?l'])))
        move = Expression(('pvar_expr', ('move', ['?l'])))
        deceleration = Expression(
            ('prod', (('typed_var', ('?z', 'zone')),
                      Expression(('pvar_expr', ('deceleration', ['?z']))))))

        mean = Expression(
            ('+', (location, Expression(('*', (deceleration, move))))))
        variance = Expression(('*', (Expression(
            ('pvar_expr', ('MOVE_VARIANCE_MULT', ['?l']))), move)))
        normal = Expression(('randomvar', ('Normal', (mean, variance))))

        deps = rddl.get_dependencies(normal)
        assert isinstance(deps, set)
        assert len(deps) == 5
        deps = set(map(lambda fluent: str(fluent), deps))
        assert deps == {
            'location/1', 'move/1', 'DECELERATION_ZONE_CENTER/2',
            'DECELERATION_ZONE_DECAY/1', 'MOVE_VARIANCE_MULT/1'
        }
Example #10
0
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))
Example #11
0
 def p_case_expr(self, p):
     '''case_expr : penum_expr
                  | pvar_expr
                  | numerical_expr'''
     p[0] = Expression(p[1])
Example #12
0
 def p_term(self, p):
     '''term : VAR
             | ENUM_VAL
             | pvar_expr'''
     p[0] = Expression(p[1]) if isinstance(
         p[1], tuple) and p[1][0] == 'pvar_expr' else p[1]
Example #13
0
    def setUpClass(cls):

        cls.zero = Expression(('number', 0.0))
        cls.one = Expression(('number', 1.0))
        cls.two = Expression(('+', (cls.one, cls.one)))

        cls.z = Expression(('randomvar', ('Normal', (cls.zero, cls.one))))
        cls.mu = Expression(('pvar_expr', ('mu', ['?x'])))
        cls.sigma = Expression(('pvar_expr', ('sigma', ['?x'])))

        cls.x1 = Expression(('randomvar', ('Normal', (cls.mu, cls.one))))
        cls.x2 = Expression(('randomvar', ('Normal', (cls.zero, cls.sigma))))
        cls.x3 = Expression(('randomvar', ('Normal', (cls.mu, cls.sigma))))

        cls.x4 = Expression(('randomvar', ('Normal', (cls.z, cls.one))))
        cls.x5 = Expression(('randomvar', ('Normal', (cls.x1, cls.one))))
        cls.x6 = Expression(('randomvar', ('Normal', (cls.x1, cls.sigma))))

        cls.mu_plus_z = Expression(('+', (cls.mu, cls.z)))
        cls.z_plus_mu = Expression(('+', (cls.z, cls.mu)))

        cls.mu_plus_x2 = Expression(('+', (cls.mu, cls.x2)))
        cls.x2_plus_mu = Expression(('+', (cls.x2, cls.mu)))

        cls.x1_plus_z = Expression(('+', (cls.x1, cls.z)))
        cls.z_plus_x1 = Expression(('+', (cls.z, cls.x1)))

        cls.z_times_z = Expression(('*', (cls.z, cls.z)))
        cls.x2_times_x2 = Expression(('*', (cls.x2, cls.x2)))

        cls.x7 = Expression(('randomvar', ('Normal', (cls.one, cls.z_times_z))))
        cls.x8 = Expression(('randomvar', ('Normal', (cls.mu, cls.z_times_z))))
        cls.x9 = Expression(('randomvar', ('Normal', (cls.x3, cls.z_times_z))))

        cls.exp_2 = Expression(('func', ('exp', [cls.two])))
        cls.exp_z = Expression(('func', ('exp', [cls.z])))
        cls.exp_x1 = Expression(('func', ('exp', [cls.x1])))

        cls.y1 = Expression(('randomvar', ('Normal', (cls.one, cls.exp_z))))
        cls.y2 = Expression(('randomvar', ('Normal', (cls.mu, cls.exp_z))))
        cls.y3 = Expression(('randomvar', ('Normal', (cls.mu, cls.exp_x1))))

        cls.gamma_shape = Expression(('pvar_expr', ('shape', ['?r'])))
        cls.gamma_scale = Expression(('pvar_expr', ('scale', ['?r'])))
        cls.gamma1 = Expression(('randomvar', ('Gamma', (cls.gamma_shape, cls.gamma_scale))))

        cls.exp_rate = Expression(('pvar_expr', ('rate', ['?r'])))
        cls.exp1 = Expression(('randomvar', ('Exponential', (cls.exp_rate,))))