Пример #1
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
Пример #2
0
    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))
Пример #3
0
 def name(self) -> str:
     '''Returns the CPF's pvariable name.'''
     return Expression._pvar_to_name(self.pvar[1])
Пример #4
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))