Source code for tests.test_spaces

# Copyright (c) 2020, Fabio Muratore, Honda Research Institute Europe GmbH, and
# Technical University of Darmstadt.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of Fabio Muratore, Honda Research Institute Europe GmbH,
#    or Technical University of Darmstadt, nor the names of its contributors may
#    be used to endorse or promote products derived from this software without
#    specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL FABIO MURATORE, HONDA RESEARCH INSTITUTE EUROPE GMBH,
# OR TECHNICAL UNIVERSITY OF DARMSTADT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import math

import numpy as np
import pytest

from pyrado.spaces.box import BoxSpace
from pyrado.spaces.discrete import DiscreteSpace
from pyrado.spaces.polar import Polar2DPosVelSpace


[docs]@pytest.fixture( scope="function", params=[ (-np.ones((7,)), np.ones((7,))), (-np.ones((7, 1)), np.ones((7, 1))), (np.array([5, -math.pi / 2, -math.pi]), np.array([5, math.pi / 2, math.pi])), ], ids=["box_flatdim", "box", "half_sphere"], ) def bs(request): return BoxSpace(request.param[0], request.param[1])
[docs]@pytest.fixture( scope="function", params=[ np.array([1]), np.array([[1]]), np.array([1, 2, 3], dtype=np.int32), np.array([-2, -1, 0, 1, 2], dtype=np.int64), np.array([4, -3, 5, 0, 1, 2, 6, -7], dtype=np.int32), np.array([4.0, -3, 5, 0, 1, 2, 6, -7], dtype=np.float64), ], ids=["scalar1dim", "scalar2dim", "pos", "pos_neg", "prandom", "prandom_float"], ) def ds(request): return DiscreteSpace(request.param)
[docs]def test_sample_contains_box_space(bs): for _ in range(10): ele = bs.sample_uniform() assert bs.contains(ele)
[docs]def test_contains_verbose_box_space(): bs = BoxSpace([-1, -2, -3], [1, 2, 3]) not_ele = np.array([-4, 0, 4]) f = bs.contains(not_ele, verbose=True) assert not f
[docs]def test_copy_box_space(bs): bsc = bs.copy() assert id(bs) != id(bsc) bs.bound_lo *= -3 assert np.all(bs.bound_lo != bsc.bound_lo) bsc.bound_up *= 5 assert np.all(bs.bound_up != bsc.bound_up)
[docs]def test_project_to_box_space(bs): for _ in range(100): # Sample from within the space w.p. 1/5 and from outside the space w.p. 4/5 ele_s = bs.sample_uniform() * 5.0 ele_p = bs.project_to(ele_s) assert bs.contains(ele_p)
[docs]def test_flat_dim_box_space(bs): print(bs.flat_dim)
[docs]@pytest.mark.parametrize( "idcs", [ [0, 1, 2], [0, 2], ], ids=["3_wo_gap", "2_w_gap"], ) def test_subspace_box_space(bs, idcs): subbox = bs.subspace(idcs) if len(bs.shape) == 1: assert subbox.flat_dim == len(idcs) np.testing.assert_equal(subbox.bound_lo, bs.bound_lo[idcs]) np.testing.assert_equal(subbox.bound_up, bs.bound_up[idcs]) np.testing.assert_equal(subbox.labels, bs.labels[idcs]) elif len(bs.shape) == 2: assert subbox.flat_dim == len(idcs) * bs.shape[1] np.testing.assert_equal(subbox.bound_lo, bs.bound_lo[idcs, :]) np.testing.assert_equal(subbox.bound_up, bs.bound_up[idcs, :]) np.testing.assert_equal(subbox.labels, bs.labels[idcs, :])
[docs]@pytest.mark.parametrize( "bs_list", [ [BoxSpace([-1, -2, -3], [1, 2, 3]), BoxSpace([-11, -22, -33], [11, 22, 33])], [BoxSpace([-1], [1]), BoxSpace([-22, 33], [22, 33])], ], ids=["identical_sizes", "different_sizes"], ) def test_cat_box_space(bs_list): bs_cat = BoxSpace.cat(bs_list) assert isinstance(bs_cat, BoxSpace) assert bs_cat.flat_dim == sum([bs.flat_dim for bs in bs_list])
[docs]@pytest.mark.parametrize( "ds_list", [ [DiscreteSpace([-1, -2, -3]), DiscreteSpace([11, 22, 33])], [DiscreteSpace([-1]), DiscreteSpace([22, 33])], ], ids=["identical_sizes", "different_sizes"], ) def test_cat_discrete_space(ds_list): ds_cat = DiscreteSpace.cat(ds_list) assert isinstance(ds_cat, DiscreteSpace) assert ds_cat.num_ele == sum([ds.num_ele for ds in ds_list])
[docs]def test_sample_contains_discrete_space(ds): for _ in range(10): ele = ds.sample_uniform() assert ds.contains(ele)
[docs]def test_copy_discrete_space(ds): dsc = ds.copy() assert id(ds) != id(dsc) ds.bound_lo *= -3 assert np.all(ds.bound_lo != dsc.bound_lo) dsc.bound_up *= 5 assert np.all(ds.bound_up != dsc.bound_up)
[docs]def test_project_to_discrete_space(ds): for _ in range(100): # Sample from within the space and from outside the space ele_s = ds.sample_uniform() * 5.0 ele_p = ds.project_to(ele_s) assert ds.contains(ele_p)
[docs]def test_torus2D(): # Parametrize within the test to hape tailored asserts torus_0deg = Polar2DPosVelSpace(np.array([1, 0, -0.1, -0.1]), np.array([1, 0, 0.1, 0.1])) sample_0deg = torus_0deg.sample_uniform() assert sample_0deg[0] == 1 # x position assert sample_0deg[1] == 0 # y position torus_90deg = Polar2DPosVelSpace(np.array([1, np.pi / 2, 0, 0]), np.array([1, np.pi / 2, 0, 0])) sample_90deg = torus_90deg.sample_uniform() assert np.all(np.isclose(sample_90deg, np.array([0, 1, 0, 0])))
[docs]def test_string_representation(bs): assert str(bs)