コード例 #1
0
    def __init__(self, left, right):
        """
        Constructor.

        Args:
            left (Distribution, numpy.ndarray):
                Left hand side.
            right (Distribution, numpy.ndarray):
                Right hand side.
        """
        repr_args = [left, right]
        exclusion = None
        if isinstance(left, Distribution):
            if left.stochastic_dependent:
                raise chaospy.StochasticallyDependentError(
                    "Joint distribution with dependencies not supported.")
        else:
            left = numpy.atleast_1d(left)
        if isinstance(right, Distribution):
            if right.stochastic_dependent:
                raise chaospy.StochasticallyDependentError(
                    "Joint distribution with dependencies not supported.")
        else:
            right = numpy.atleast_1d(right)
        super(Trunc, self).__init__(
            left=left,
            right=right,
            repr_args=repr_args,
        )
コード例 #2
0
ファイル: truncation.py プロジェクト: jonathf/chaospy
    def __init__(self, dist, lower=None, upper=None):
        """
        Constructor.

        Args:
            dist (Distribution):
                Distribution to be truncated.
            lower (Distribution, numpy.ndarray):
                Lower truncation bound.
            upper (Distribution, numpy.ndarray):
                Upper truncation bound.
        """
        assert isinstance(dist, Distribution)
        repr_args = [dist]
        repr_args += chaospy.format_repr_kwargs(lower=(lower, None))
        repr_args += chaospy.format_repr_kwargs(upper=(upper, None))
        exclusion = set()
        for deps in dist._dependencies:
            exclusion.update(deps)
        if isinstance(lower, Distribution):
            if lower.stochastic_dependent:
                raise chaospy.StochasticallyDependentError(
                    "Joint distribution with dependencies not supported."
                )
            assert len(dist) == len(lower)
            lower_ = lower.lower
        elif lower is None:
            lower = lower_ = dist.lower
        else:
            lower = lower_ = numpy.atleast_1d(lower)
        if isinstance(upper, Distribution):
            if upper.stochastic_dependent:
                raise chaospy.StochasticallyDependentError(
                    "Joint distribution with dependencies not supported."
                )
            assert len(dist) == len(upper)
            upper_ = upper.upper
        elif upper is None:
            upper = upper_ = dist.upper
        else:
            upper = upper_ = numpy.atleast_1d(upper)
        assert numpy.all(
            upper_ > lower_
        ), "condition `upper > lower` not satisfied: %s <= %s" % (upper_, lower_)

        dependencies, parameters, rotation = chaospy.declare_dependencies(
            distribution=self,
            parameters=dict(lower=lower, upper=upper),
            length=len(dist),
        )
        super(Trunc, self).__init__(
            parameters=parameters,
            dependencies=dependencies,
            exclusion=exclusion,
            repr_args=repr_args,
        )
        self._dist = dist
コード例 #3
0
ファイル: multiply.py プロジェクト: jonathf/chaospy
    def _mom(self, key, left, right, cache):
        """
        Statistical moments.

        Example:
            >>> chaospy.Uniform().mom([0, 1, 2, 3]).round(4)
            array([1.    , 0.5   , 0.3333, 0.25  ])
            >>> Multiply(chaospy.Uniform(), 2).mom([0, 1, 2, 3]).round(4)
            array([1.    , 1.    , 1.3333, 2.    ])
            >>> Multiply(2, chaospy.Uniform()).mom([0, 1, 2, 3]).round(4)
            array([1.    , 1.    , 1.3333, 2.    ])
            >>> Multiply(chaospy.Uniform(), chaospy.Uniform()).mom([0, 1, 2, 3]).round(4)
            array([1.    , 0.25  , 0.1111, 0.0625])

        """
        del cache
        if isinstance(left, Distribution):
            if chaospy.shares_dependencies(left, right):
                raise chaospy.StochasticallyDependentError(
                    "product of dependent distributions not feasible: "
                    "{} and {}".format(left, right)
                )
            left = left._get_mom(key)
        else:
            left = (numpy.array(left).T ** key).T
        if isinstance(right, Distribution):
            right = right._get_mom(key)
        else:
            right = (numpy.array(right).T ** key).T
        return numpy.prod(left) * numpy.prod(right)
コード例 #4
0
ファイル: distribution.py プロジェクト: yoelcortes/chaospy
    def cdf(self, x_data):
        """
        Cumulative distribution function.

        Note that chaospy only supports cumulative distribution functions for
        stochastically independent distributions.

        Args:
            x_data (numpy.ndarray):
                Location for the distribution function. Assumes that
                ``len(x_data) == len(distribution)``.

        Returns:
            (numpy.ndarray):
                Evaluated distribution function values, where output has shape
                ``x_data.shape`` in one dimension and ``x_data.shape[1:]`` in
                higher dimensions.
        """
        check_dependencies(self)
        if self.stochastic_dependent:
            raise chaospy.StochasticallyDependentError(
                "Cumulative distribution does not support dependencies.")
        x_data = numpy.asarray(x_data)
        if self.interpret_as_integer:
            x_data = x_data + 0.5
        q_data = self.fwd(x_data)
        if len(self) > 1:
            q_data = numpy.prod(q_data, 0)
        return q_data
コード例 #5
0
ファイル: utils.py プロジェクト: yuanyuansjtu/chaospy
def declare_dependencies(
    distribution,
    parameters,
    rotation=None,
    is_operator=False,
    dependency_type="iid",
    length=None,
):
    """
    Convenience function for declaring distribution dependencies.

    Iterates through parameters to figure out what a distribution dependency
    structure should be.

    Args:
        distribution (chaospy.Distribution):
            The distributions to to declare dependencies for.
        parameters (Dict[str, Any]):
            The distribution parameters that should be included in the
            declaration.
        is_operator (bool):
            Operators do not themselves contain uncertainty, but only inherits
            from parameters and/or wrapped distribution.
        wrapper_dist (Optional[chaospy.Distribution]):
            Distributions that are thin-wrappers to some other distribution
            should inherent dependencies.
    """
    parameters = parameters.copy()
    for name, parameter in list(parameters.items()):
        if not isinstance(parameter, chaospy.Distribution):
            parameters[name] = numpy.atleast_1d(parameter)
    if length is None:
        if rotation is None:
            length = max([len(parameter)
                          for parameter in parameters.values()] + [1])
        else:
            length = len(rotation)
    if rotation is None:
        rotation = numpy.arange(length, dtype=int)
    else:
        rotation = numpy.asarray(rotation)

    if is_operator:
        dependencies = [set() for _ in range(length)]
    else:
        dependencies = init_dependencies(distribution,
                                         rotation,
                                         dependency_type=dependency_type)

    for name, parameter in list(parameters.items()):
        if isinstance(parameter, chaospy.Distribution):
            if len(parameter) != length:
                raise chaospy.StochasticallyDependentError(
                    "dependencies must be same length as parent")
            for dep1, dep2 in zip(dependencies, parameter._dependencies):
                dep1.update(dep2)
        else:
            parameters[name] = parameter * numpy.ones(length, dtype=int)
    return dependencies, parameters, rotation
コード例 #6
0
ファイル: mean_covariance.py プロジェクト: yoelcortes/chaospy
 def _ttr(self, kloc, idx, mean, sigma, dim, mut, cache):
     if dim > 1:
         raise chaospy.StochasticallyDependentError(
             "TTR require stochastically independent components.")
     coeff0, coeff1 = self._dist._get_ttr(kloc, idx)
     coeff0 = coeff0 * sigma + mean[dim]
     coeff1 = coeff1 * sigma * sigma
     return coeff0, coeff1
コード例 #7
0
 def _ttr(self, kloc, idx, left, right, cache):
     """Three terms recurrence coefficients."""
     del cache
     if isinstance(right, Distribution):
         if isinstance(left, Distribution):
             raise chaospy.StochasticallyDependentError(
                 "product of distributions not feasible: "
                 "{} and {}".format(left, right))
         left, right = right, left
     coeff0, coeff1 = left._get_ttr(kloc, idx)
     return coeff0 * right, coeff1 * right * right
コード例 #8
0
ファイル: mean_covariance.py プロジェクト: yoelcortes/chaospy
    def get_parameters(self, idx, cache, assert_numerical=True):
        parameters = super(MeanCovarianceDistribution, self).get_parameters(
            idx, cache, assert_numerical=assert_numerical)

        mean = parameters["mean"]
        if idx is None:
            return dict(mean=mean, sigma=self._covariance, cache=cache)

        if isinstance(mean, Distribution):
            mean = [
                mean._get_cache(dim, cache, get=0) for dim in range(len(mean))
            ]
            if any([
                    isinstance(condition, chaospy.Distribution)
                    for condition in mean
            ]):
                raise chaospy.StochasticallyDependentError(
                    "Dangling dependency: %s | %s" % (self, mean))
            mean = numpy.array(mean)
        mean = mean[self._rotation]

        dim = self._rotation.index(idx)
        if dim:
            covinv = numpy.linalg.inv(self._pcovariance[:dim, :dim])
            sigma = numpy.sqrt(self._pcovariance[dim, dim] - self._pcovariance[
                dim, :dim].dot(covinv).dot(self._pcovariance[:dim, dim]))
            mu_transform = self._pcovariance[dim, :dim].dot(covinv)
            assert numpy.isfinite(sigma), (dim, self._pcovariance)
        else:
            sigma = numpy.sqrt(self._pcovariance[0, 0])
            mu_transform = 0

        return dict(idx=idx,
                    mean=mean,
                    sigma=sigma,
                    dim=dim,
                    mut=mu_transform,
                    cache=cache)
コード例 #9
0
    def _mom(self, keys, left, right, cache):
        """
        Statistical moments.

        Example:
            >>> chaospy.Uniform().mom([0, 1, 2, 3]).round(4)
            array([1.    , 0.5   , 0.3333, 0.25  ])
            >>> chaospy.Add(chaospy.Uniform(), 2).mom([0, 1, 2, 3]).round(4)
            array([ 1.    ,  2.5   ,  6.3333, 16.25  ])
            >>> chaospy.Add(2, chaospy.Uniform()).mom([0, 1, 2, 3]).round(4)
            array([ 1.    ,  2.5   ,  6.3333, 16.25  ])

        """
        del cache
        keys_ = numpy.mgrid[tuple(slice(0, key + 1, 1) for key in keys)]
        keys_ = keys_.reshape(len(self), -1)

        if isinstance(left, Distribution):
            if chaospy.shares_dependencies(left, right):
                raise chaospy.StochasticallyDependentError(
                    "%s: left and right side of sum stochastically dependent."
                    % self)
            left = [left._get_mom(key) for key in keys_.T]
        else:
            left = list(reversed(numpy.array(left).T**keys_.T))

        if isinstance(right, Distribution):
            right = [right._get_mom(key) for key in keys_.T]
        else:
            right = list(
                reversed(numpy.prod(numpy.array(right).T**keys_.T, -1)))

        out = 0.0
        for idx in range(keys_.shape[1]):
            key = keys_.T[idx]
            coef = numpy.prod(comb(keys, key))
            out += coef * left[idx] * right[idx] * numpy.all(key <= keys)
        return out
コード例 #10
0
ファイル: openturns_.py プロジェクト: yuanyuansjtu/chaospy
 def __init__(self, distribution):
     from openturns import ComposedDistribution, ContinuousDistribution
     if isinstance(distribution, ComposedDistribution):
         if not distribution.hasIndependentCopula():
             raise chaospy.StochasticallyDependentError(
                 "Stochastically dependent "
                 "OpenTURNS distribution unsupported")
         distributions = [
             openturns_dist(dist)
             for dist in distribution.getDistributionCollection()
         ]
     elif isinstance(distribution, ContinuousDistribution):
         distributions = [openturns_dist(distribution)]
     else:
         assert isinstance(distribution, Iterable) and all(
             [
                 isinstance(dist, ContinuousDistribution)
                 for dist in distribution
             ]
         ), "Only (iterable of) continuous OpenTURNS distributions supported"
         distributions = [openturns_dist(dist) for dist in distribution]
     super(OpenTURNSDist, self).__init__(*distributions)
     self._repr_args = [distributions]
コード例 #11
0
ファイル: utils.py プロジェクト: dwstephens/chaospy
def check_dependencies(distribution):
    """
    Check if the dependency structure is valid.

    Rosenblatt transformations, density calculations etc. assumes that the
    input and output of transformation is the same. It also assumes that there
    is a order defined in `distribution._rotation` so an decomposition on the
    form `p(x0), p(x1|x0), ...` is possible.

    This should be checked on function calls, not init, as it does not apply to
    e.g. moment and three-terms-recurrence calculations.

    Args:
        distribution:
            The distribution to verify is correctly set up.

    Raises:
        StochasticallyDependentError:
            If invalid dependency structure is present.

    Examples:
        >>> dist = chaospy.Uniform(0, 1)
        >>> chaospy.check_dependencies(dist)
        >>> chaospy.check_dependencies(chaospy.Normal(mu=dist))
        Traceback (most recent call last):
            ...
        chaospy.StochasticallyDependentError: \
Normal(mu=Uniform(), sigma=1) has dangling dependencies

    """
    current = set()
    for idx in distribution._rotation:
        length = len(current)
        current.update(distribution._dependencies[idx])
        if len(current) != length + 1:
            raise chaospy.StochasticallyDependentError(
                "%s has dangling dependencies" % distribution)
コード例 #12
0
def quad_leja(
    order,
    dist,
    rule="fejer",
    accuracy=100,
    recurrence_algorithm="",
):
    """
    Generate Leja quadrature node.

    Args:
        order (int):
            The order of the quadrature.
        dist (chaospy.distributions.baseclass.Distribution):
            The distribution which density will be used as weight function.
        rule (str):
            In the case of ``lanczos`` or ``stieltjes``, defines the
            proxy-integration scheme.
        accuracy (int):
            In the case ``rule`` is used, defines the quadrature order of the
            scheme used. In practice, must be at least as large as ``order``.
        recurrence_algorithm (str):
            Name of the algorithm used to generate abscissas and weights. If
            omitted, ``analytical`` will be tried first, and ``stieltjes`` used
            if that fails.

    Returns:
        (numpy.ndarray, numpy.ndarray):
            abscissas:
                The quadrature points for where to evaluate the model function
                with ``abscissas.shape == (len(dist), N)`` where ``N`` is the
                number of samples.
            weights:
                The quadrature weights with ``weights.shape == (N,)``.

    Example:
        >>> abscissas, weights = quad_leja(3, chaospy.Normal(0, 1))
        >>> abscissas.round(4)
        array([[-2.7173, -1.4142,  0.    ,  1.7635]])
        >>> weights.round(4)
        array([0.022 , 0.1629, 0.6506, 0.1645])
    """
    if len(dist) > 1:
        if dist.stochastic_depedent:
            raise chaospy.StochasticallyDependentError(
                "Leja quadrature do not supper distribution with dependencies."
            )
        if isinstance(order, int):
            out = [quad_leja(order, _) for _ in dist]
        else:
            out = [quad_leja(order[_], dist[_]) for _ in range(len(dist))]

        abscissas = [_[0][0] for _ in out]
        weights = [_[1] for _ in out]
        abscissas = combine(abscissas).T
        weights = combine(weights)
        weights = numpy.prod(weights, -1)

        return abscissas, weights

    abscissas = [dist.lower, dist.mom(1).flatten(), dist.upper]
    for _ in range(int(order)):

        def objective(abscissas_):
            """Local objective function."""
            out = -numpy.sqrt(dist.pdf(abscissas_)) * numpy.prod(
                numpy.abs(abscissas[1:-1] - abscissas_))
            return out

        def fmin(idx):
            """Bound minimization."""
            try:
                x, fx = fminbound(objective,
                                  abscissas[idx],
                                  abscissas[idx + 1],
                                  full_output=1)[:2]
            except UnboundLocalError:
                x = abscissas[idx] + 0.5 * (3 - 5**0.5) * (abscissas[idx + 1] -
                                                           abscissas[idx])
                fx = objective(x)
            return x, fx

        opts, vals = zip(*[fmin(idx) for idx in range(len(abscissas) - 1)])
        index = numpy.argmin(vals)
        abscissas.insert(index + 1, opts[index])

    abscissas = numpy.asfarray(abscissas).flatten()[1:-1]
    weights = create_weights(abscissas, dist, rule, accuracy,
                             recurrence_algorithm)
    abscissas = abscissas.reshape(1, abscissas.size)

    return numpy.asfarray(abscissas), numpy.asfarray(weights).flatten()
コード例 #13
0
ファイル: samples.py プロジェクト: yuanyuansjtu/chaospy
 def _mom(self, k, lo, up):
     if self.unbound:
         return numpy.prod(numpy.mean(self.samples.T**k, -1))
     raise chaospy.StochasticallyDependentError("component lack support")
コード例 #14
0
 def _ttr(self, kloc, parent, parameters):
     raise chaospy.StochasticallyDependentError("TTR not supported")
コード例 #15
0
ファイル: utils.py プロジェクト: dwstephens/chaospy
def declare_dependencies(
    distribution,
    parameters,
    rotation=None,
    is_operator=False,
    dependency_type="iid",
    length=None,
    extra_parameters=None,
):
    """
    Convenience function for declaring distribution dependencies.

    Iterates through parameters to figure out what a distribution dependency
    structure should be.

    Args:
        distribution (chaospy.Distribution):
            The distributions to to declare dependencies for.
        parameters (Dict[str, Any]):
            The distribution parameters that should be included in the
            declaration.
        rotation (Optional[Sequence[int]]):
            The order of which the dependencies should be resolved.
            Automatically calculated if omitted.
        is_operator (bool):
            Operators do not themselves contain uncertainty, but only inherits
            from parameters and/or wrapped distribution.
        wrapper_dist (Optional[chaospy.Distribution]):
            Distributions that are thin-wrappers to some other distribution
            should inherent dependencies.
        extra_parameters(Optional[Dict[str, Any]]):
            Extra parameters that should be included in the declaration, but
            not considered a direct part of the distribution. Assumed to be
            pre-processed.

    Returns:
        dependencies (List[Set[int]]):
            Dependency reference numbers, one collection per dimension. Single
            element implies stochstically independent.
        parameters (Dict[str, Any]):
            Same as `parameters`, but updated to all conform to the same size.
        rotation (List[int]):
            Same as `rotation` if provided. If not, the automatically
            calculated one is returned.

    """
    extra_parameters = extra_parameters.copy() if extra_parameters else {}
    parameters = parameters.copy()
    for name, parameter in list(parameters.items()):
        if not isinstance(parameter, chaospy.Distribution):
            parameters[name] = numpy.atleast_1d(parameter)
    if length is None:
        if rotation is None:
            length = max(
                [len(parameter) for parameter in extra_parameters.values()] +
                [len(parameter) for parameter in parameters.values()] + [1])
        else:
            length = len(rotation)
    if rotation is None:
        rotation = numpy.arange(length, dtype=int)
    else:
        rotation = numpy.asarray(rotation)

    if is_operator:
        dependencies = [set() for _ in range(length)]
    else:
        dependencies = init_dependencies(distribution,
                                         rotation,
                                         dependency_type=dependency_type)

    for name, parameter in list(parameters.items()):
        if isinstance(parameter, chaospy.Distribution):
            if len(parameter) != length:
                raise chaospy.StochasticallyDependentError(
                    "dependencies must be same length as parent")
        else:
            parameters[name] = parameter * numpy.ones(length, dtype=int)
    for name, parameter in list(parameters.items()) + list(
            extra_parameters.items()):
        if isinstance(parameter, chaospy.Distribution):
            for dep1, dep2 in zip(dependencies, parameter._dependencies):
                dep1.update(dep2)
    assert len(dependencies) == length
    return dependencies, parameters, rotation
コード例 #16
0
ファイル: leja.py プロジェクト: yoelcortes/chaospy
def quad_leja(
    order,
    dist,
    rule="fejer",
):
    """
    Generate Leja quadrature node.

    Args:
        order (int):
            The order of the quadrature.
        dist (chaospy.distributions.baseclass.Distribution):
            The distribution which density will be used as weight function.
        rule (str):
            In the case of ``lanczos`` or ``stieltjes``, defines the
            proxy-integration scheme.

    Returns:
        (numpy.ndarray, numpy.ndarray):
            abscissas:
                The quadrature points for where to evaluate the model function
                with ``abscissas.shape == (len(dist), N)`` where ``N`` is the
                number of samples.
            weights:
                The quadrature weights with ``weights.shape == (N,)``.

    Notes:
        Implemented as proposed in Narayan and Jakeman
        :cite:`narayan_adaptive_2014`.

    Example:
        >>> abscissas, weights = quad_leja(
        ...     2, chaospy.Iid(chaospy.Normal(0, 1), 2))
        >>> abscissas.round(2)
        array([[-1.41, -1.41, -1.41,  0.  ,  0.  ,  0.  ,  1.76,  1.76,  1.76],
               [-1.41,  0.  ,  1.76, -1.41,  0.  ,  1.76, -1.41,  0.  ,  1.76]])
        >>> weights.round(3)
        array([0.05 , 0.133, 0.04 , 0.133, 0.359, 0.107, 0.04 , 0.107, 0.032])

    """
    if len(dist) > 1:
        if dist.stochastic_dependent:
            raise chaospy.StochasticallyDependentError(
                "Leja quadrature do not supper distribution with dependencies."
            )
        order = numpy.broadcast_to(order, len(dist))
        out = [quad_leja(order[_], dist[_]) for _ in range(len(dist))]
        abscissas = [_[0][0] for _ in out]
        weights = [_[1] for _ in out]
        abscissas = combine(abscissas).T
        weights = combine(weights)
        weights = numpy.prod(weights, -1)

        return abscissas, weights

    abscissas = [dist.lower, dist.mom(1).flatten(), dist.upper]
    for _ in range(int(order)):

        def objective(abscissas_):
            """Local objective function."""
            out = -numpy.sqrt(dist.pdf(abscissas_)) * numpy.prod(
                numpy.abs(abscissas[1:-1] - abscissas_))
            return out

        def fmin(idx):
            """Bound minimization."""
            try:
                xopt, fval, _, _ = fminbound(objective,
                                             abscissas[idx],
                                             abscissas[idx + 1],
                                             full_output=True)
            # Hard coded solution to scipy/scipy#11207 for scipy < 1.5.0.
            except UnboundLocalError:  # pragma: no cover
                xopt = abscissas[idx] + 0.5 * (3 - 5**0.5) * (
                    abscissas[idx + 1] - abscissas[idx])
                fx = objective(xopt)
            return xopt, fval

        opts, vals = zip(*[fmin(idx) for idx in range(len(abscissas) - 1)])
        index = numpy.argmin(vals)
        abscissas.insert(index + 1, opts[index])

    abscissas = numpy.asfarray(abscissas).flatten()[1:-1]
    weights = create_weights(abscissas, dist, rule)
    abscissas = abscissas.reshape(1, abscissas.size)

    return numpy.asfarray(abscissas), numpy.asfarray(weights).flatten()
コード例 #17
0
ファイル: distribution.py プロジェクト: yoelcortes/chaospy
    def __init__(
        self,
        parameters,
        dependencies,
        rotation=None,
        exclusion=None,
        repr_args=None,
    ):
        """
        Distribution initializer.

        In addition to assigning some object variables, also checks for
        some consistency issues.

        Args:
            parameters (Optional[Distribution[str, Union[ndarray, Distribution]]]):
                Collection of model parameters.
            dependencies (Optional[Sequence[Set[int]]]):
                Dependency identifiers. One collection for each dimension.
            rotation (Optional[Sequence[int]]):
                The order of which to resolve dependencies.
            exclusion (Optional[Sequence[int]]):
                Distributions that has been "taken out of play" and
                therefore can not be reused other places in the
                dependency hierarchy.
            repr_args (Optional[Sequence[str]]):
                Positional arguments to place in the object string
                representation. The repr output will then be:
                `<class name>(<arg1>, <arg2>, ...)`.

        Raises:
            StochasticallyDependentError:
                For dependency structures that can not later be
                rectified. This include under-defined
                distributions, and inclusion of distributions that
                should be exclusion.

        """
        assert isinstance(parameters, dict)
        self._parameters = parameters
        self._dependencies = list(dependencies)
        if rotation is None:
            rotation = sorted(enumerate(self._dependencies),
                              key=lambda x: len(x[1]))
            rotation = [key for key, _ in rotation]
        rotation = list(rotation)
        assert len(set(rotation)) == len(dependencies)
        assert min(rotation) == 0
        assert max(rotation) == len(dependencies) - 1
        self._rotation = rotation
        if exclusion is None:
            exclusion = set()
        self._exclusion = set(exclusion)
        if repr_args is None:
            repr_args = ("{}={}".format(key, self._parameters[key])
                         for key in sorted(self._parameters))
        self._repr_args = list(repr_args)
        self._mom_cache = {(0, ) * len(dependencies): 1.}
        self._ttr_cache = {}
        self._indices = {}

        self._all_dependencies = {
            dep
            for deps in self._dependencies for dep in deps
        }
        if len(self._all_dependencies) < len(dependencies):
            raise chaospy.StochasticallyDependentError(
                "%s is an under-defined probability distribution." % self)

        for key, param in list(parameters.items()):
            if isinstance(param, Distribution):
                if self._all_dependencies.intersection(param._exclusion):
                    raise chaospy.StochasticallyDependentError(
                        ("%s contains dependencies that can not also exist "
                         "other places in the dependency hierarchy") % param)
                self._exclusion.update(param._exclusion)
            else:
                self._parameters[key] = numpy.asarray(param)