示例#1
0
    def from_tuples(cls, bounds: Iterable[tuple]) -> "Bounds":
        """
        Instantiate a :class:`Bounds` from a collection of tuples containing \
        the higher and lower bounds for every dimension as a tuple.

        Args:
            bounds: Iterable that returns tuples containing the higher and lower \
                    bound for every dimension of the target bounds.

        Returns:
                :class:`Bounds` instance.

        Examples:
            >>> intervals = ((-1, 1), (-2, 1), (2, 3))
            >>> bounds = Bounds.from_tuples(intervals)
            >>> print(bounds)
            Bounds shape int64 dtype (3,) low [-1 -2  2] high [1 1 3]

        """
        low, high = [], []
        for lo, hi in bounds:
            low.append(lo)
            high.append(hi)
        low, high = tensor(low, dtype=dtype.float), tensor(high,
                                                           dtype=dtype.float)
        return Bounds(low=low, high=high)
示例#2
0
 def merge_one_name(states_list, name):
     vals = []
     for state in states_list:
         data = state[name]
         # Attributes that are not tensors are not stacked.
         if not judo.is_tensor(data):
             return data
         state_len = len(state)
         if len(data.shape) == 0 and state_len == 1:
             # Name is scalar vector. Data is typing.Scalar value. Transform to array first
             value = tensor([data]).flatten()
         elif len(data.shape) == 1 and state_len == 1:
             if data.shape[0] == 1:
                 # Name is typing.Scalar vector. Data already transformed to an array
                 value = data
             else:
                 # Name is a matrix of vectors. Data needs an additional dimension
                 value = tensor([data])
         elif len(data.shape) == 1 and state_len > 1:
             # Name is a typing.Scalar vector. Data already has is a one dimensional array
             value = data
         elif (len(data.shape) > 1 and state_len > 1
               or len(data.shape) > 1 and len(state) == 1):
             # Name is a matrix of vectors. Data has the correct shape
             value = data
         else:
             raise ValueError(
                 "Could not infer data concatenation for attribute %s  with shape %s"
                 % (name, data.shape), )
         vals.append(value)
     return API.concatenate(vals)
示例#3
0
def calculate_clone(virtual_rewards: Tensor, oobs: Tensor = None, eps=1e-3):
    """Calculate the clone indexes and masks from the virtual rewards."""
    compas_ix = get_alive_indexes(oobs) if oobs is not None else judo.arange(
        len(virtual_rewards))
    compas_ix = random_state.permutation(compas_ix)
    vir_rew = virtual_rewards.flatten()
    clone_probs = (vir_rew[compas_ix] - vir_rew) / judo.where(
        vir_rew > eps, vir_rew, tensor(eps))
    will_clone = clone_probs.flatten() > random_state.random(len(clone_probs))
    return compas_ix, will_clone
示例#4
0
    def get_scaled_intervals(
        low: Union[Tensor, float, int],
        high: Union[Tensor, float, int],
        scale: float,
    ) -> Tuple[Union[Tensor, float], Union[Tensor, float]]:
        """
        Scale the high and low vectors by an scale factor.

        The value of the high and low will be proportional to the maximum and minimum values of \
        the array. Scale defines the proportion to make the bounds bigger and smaller. For \
        example, if scale is 1.1 the higher bound will be 10% higher, and the lower bounds 10% \
        smaller. If scale is 0.9 the higher bound will be 10% lower, and the lower bound 10% \
        higher. If scale is one, `high` and `low` will be equal to the maximum and minimum values \
        of the array.

        Args:
            high: Higher bound to be scaled.
            low: Lower bound to be scaled.
            scale: Value representing the tolerance in percentage from the current maximum and \
            minimum values of the array.

        Returns:
            :class:`Bounds` instance.

        """
        pct = tensor(scale - 1)
        big_scale = 1 + API.abs(pct)
        small_scale = 1 - API.abs(pct)
        zero = judo.astype(tensor(0.0), low.dtype)
        if pct > 0:
            xmin_scaled = API.where(low < zero, low * big_scale,
                                    low * small_scale)
            xmax_scaled = API.where(high < zero, high * small_scale,
                                    high * big_scale)
        else:
            xmin_scaled = API.where(low < zero, low * small_scale,
                                    low * small_scale)
            xmax_scaled = API.where(high < zero, high * big_scale,
                                    high * small_scale)
        return xmin_scaled, xmax_scaled
示例#5
0
def cross_clone(
    host_virtual_rewards: Tensor,
    ext_virtual_rewards: Tensor,
    host_oobs: Tensor = None,
    eps=1e-3,
):
    """Perform a clone operation between two different groups of points."""
    compas_ix = random_state.permutation(judo.arange(len(ext_virtual_rewards)))
    host_vr = judo.astype(host_virtual_rewards.flatten(), dtype=dtype.float32)
    ext_vr = judo.astype(ext_virtual_rewards.flatten(), dtype=dtype.float32)
    clone_probs = (ext_vr[compas_ix] - host_vr) / judo.where(
        ext_vr > eps, ext_vr, tensor(eps, dtype=dtype.float32))
    will_clone = clone_probs.flatten() > random_state.random(len(clone_probs))
    if host_oobs is not None:
        will_clone[host_oobs] = True
    return compas_ix, will_clone
示例#6
0
    def __init__(
        self,
        high: Union[Tensor, Scalar] = numpy.inf,
        low: Union[Tensor, Scalar] = numpy.NINF,
        shape: Optional[tuple] = None,
        dtype: Optional[type] = None,
    ):
        """
        Initialize a :class:`Bounds`.

        Args:
            high: Higher value for the bound interval. If it is an typing_.Scalar \
                  it will be applied to all the coordinates of a target vector. \
                  If it is a vector, the bounds will be checked coordinate-wise. \
                  It defines and closed interval.
            low: Lower value for the bound interval. If it is a typing_.Scalar it \
                 will be applied to all the coordinates of a target vector. \
                 If it is a vector, the bounds will be checked coordinate-wise. \
                 It defines and closed interval.
            shape: Shape of the array that will be bounded. Only needed if `high` and `low` are \
                   vectors and it is used to define the dimensions that will be bounded.
            dtype:  Data type of the array that will be bounded. It can be inferred from `high` \
                    or `low` (the type of `high` takes priority).

        Examples:
            Initializing :class:`Bounds` using  numpy arrays:

            >>> import numpy
            >>> high, low = numpy.ones(3, dtype=float), -1 * numpy.ones(3, dtype=int)
            >>> bounds = Bounds(high=high, low=low)
            >>> print(bounds)
            Bounds shape float64 dtype (3,) low [-1 -1 -1] high [1. 1. 1.]

            Initializing :class:`Bounds` using  typing_.Scalars:

            >>> import numpy
            >>> high, low, shape = 4, 2.1, (5,)
            >>> bounds = Bounds(high=high, low=low, shape=shape)
            >>> print(bounds)
            Bounds shape float64 dtype (5,) low [2.1 2.1 2.1 2.1 2.1] high [4. 4. 4. 4. 4.]

        """
        # Infer shape if not specified
        if shape is None and hasattr(high, "shape"):
            shape = high.shape
        elif shape is None and hasattr(low, "shape"):
            shape = low.shape
        elif shape is None:
            raise TypeError(
                "If shape is None high or low need to have .shape attribute.")
        # High and low will be arrays of target shape
        if not judo.is_tensor(high):
            high = tensor(high) if isinstance(
                high, _Iterable) else API.ones(shape) * high
        if not judo.is_tensor(low):
            low = tensor(low) if isinstance(
                low, _Iterable) else API.ones(shape) * low
        self.high = judo.astype(high, dtype)
        self.low = judo.astype(low, dtype)
        if dtype is not None:
            self.dtype = dtype
        elif hasattr(high, "dtype"):
            self.dtype = high.dtype
        elif hasattr(low, "dtype"):
            self.dtype = low.dtype
        else:
            self.dtype = type(high) if high is not None else type(low)
示例#7
0
def clip(x, a_min, a_max, out=None):

    _tensor = min(x, other=astype(tensor(a_max), dtype=x.dtype))
    return max(_tensor, other=astype(tensor(a_min), dtype=x.dtype), out=out)