def test_contains_all(): # 1d intvp = IntervalProd(1, 2) arr_in1 = np.array([1.0, 1.6, 1.3, 2.0]) arr_in2 = np.array([[1.0, 1.6, 1.3, 2.0]]) mesh_in = sparse_meshgrid([1.0, 1.7, 1.9]) arr_not_in1 = np.array([1.0, 1.6, 1.3, 2.0, 0.8]) arr_not_in2 = np.array([[1.0, 1.6, 2.0], [1.0, 1.5, 1.6]]) mesh_not_in = sparse_meshgrid([-1.0, 1.7, 1.9]) assert intvp.contains_all(arr_in1) assert intvp.contains_all(arr_in2) assert intvp.contains_all(mesh_in) assert not intvp.contains_all(arr_not_in1) assert not intvp.contains_all(arr_not_in2) assert not intvp.contains_all(mesh_not_in) # 2d intvp = IntervalProd([0, 0], [1, 2]) arr_in = np.array([[0.5, 1.9], [0.0, 1.0], [1.0, 0.1]]).T mesh_in = sparse_meshgrid([0, 0.1, 0.6, 0.7, 1.0], [0]) arr_not_in = np.array([[0.5, 1.9], [1.1, 1.0], [1.0, 0.1]]).T mesh_not_in = sparse_meshgrid([0, 0.1, 0.6, 0.7, 1.0], [0, -1]) assert intvp.contains_all(arr_in) assert intvp.contains_all(mesh_in) assert not intvp.contains_all(arr_not_in) assert not intvp.contains_all(mesh_not_in)
def test_equals(): interval1 = IntervalProd(1, 2) interval2 = IntervalProd(1, 2) interval3 = IntervalProd([1], [2]) interval4 = IntervalProd(2, 3) rectangle1 = IntervalProd([1, 2], [2, 3]) rectangle2 = IntervalProd((1, 2), (2, 3)) rectangle3 = IntervalProd([0, 2], [2, 3]) assert interval1 == interval1 assert not interval1 != interval1 assert interval1 == interval2 assert interval1 == interval3 assert not interval1 == interval4 assert interval1 != interval4 assert not interval1 == rectangle1 assert rectangle1 == rectangle1 assert rectangle2 == rectangle2 assert not rectangle1 == rectangle3 r1_1 = IntervalProd(-np.inf, np.inf) r1_2 = IntervalProd(-np.inf, np.inf) positive_reals = IntervalProd(0, np.inf) assert r1_1 == r1_1 assert r1_1 == r1_2 assert positive_reals == positive_reals assert positive_reals != r1_1 # non interval for non_interval in [1, 1j, np.array([1, 2])]: assert interval1 != non_interval assert rectangle1 != non_interval
def test_equals(): """Test equality check of IntervalProd.""" interval1 = IntervalProd(1, 2) interval2 = IntervalProd(1, 2) interval3 = IntervalProd([1], [2]) interval4 = IntervalProd(2, 3) rectangle1 = IntervalProd([1, 2], [2, 3]) rectangle2 = IntervalProd((1, 2), (2, 3)) rectangle3 = IntervalProd([0, 2], [2, 3]) _test_eq(interval1, interval1) _test_eq(interval1, interval2) _test_eq(interval1, interval3) _test_neq(interval1, interval4) _test_neq(interval1, rectangle1) _test_eq(rectangle1, rectangle1) _test_eq(rectangle2, rectangle2) _test_eq(rectangle1, rectangle2) _test_neq(rectangle1, rectangle3) r1_1 = IntervalProd(-np.inf, np.inf) r1_2 = IntervalProd(-np.inf, np.inf) positive_reals = IntervalProd(0, np.inf) _test_eq(r1_1, r1_1) _test_eq(r1_1, r1_2) _test_eq(positive_reals, positive_reals) _test_neq(positive_reals, r1_1) # non interval for non_interval in [1, 1j, np.array([1, 2])]: assert interval1 != non_interval assert rectangle1 != non_interval
def test_neg(): interv = IntervalProd(1, 2) assert -interv == IntervalProd(-2, -1) interv = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) assert -interv == IntervalProd([-2, -3, -4, -5, -6], [-1, -2, -3, -4, -5])
def test_volume(): set_ = IntervalProd(1, 2) assert set_.volume == 2 - 1 set_ = IntervalProd(0, np.inf) assert set_.volume == np.inf set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert almost_equal(set_.volume, (5 - 1) * (6 - 2) * (7 - 3))
def test_mid_pt(): set_ = IntervalProd(1, 2) assert set_.mid_pt == 1.5 set_ = IntervalProd(0, np.inf) assert set_.mid_pt == np.inf set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.mid_pt, [3, 4, 5])
def test_volume(): set_ = IntervalProd(1, 2) assert set_.volume == 2 - 1 set_ = IntervalProd(0, np.inf) assert set_.volume == np.inf set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert set_.volume == pytest.approx((5 - 1) * (6 - 2) * (7 - 3))
def test_insert(): intvp1 = IntervalProd([0, 0], [1, 2]) intvp2 = IntervalProd(1, 3) intvp = intvp1.insert(0, intvp2) true_min_pt = [1, 0, 0] true_max_pt = [3, 1, 2] assert intvp == IntervalProd(true_min_pt, true_max_pt) intvp = intvp1.insert(1, intvp2) true_min_pt = [0, 1, 0] true_max_pt = [1, 3, 2] assert intvp == IntervalProd(true_min_pt, true_max_pt) intvp = intvp1.insert(2, intvp2) true_min_pt = [0, 0, 1] true_max_pt = [1, 2, 3] assert intvp == IntervalProd(true_min_pt, true_max_pt) intvp = intvp1.insert(-1, intvp2) # same as 1 true_min_pt = [0, 1, 0] true_max_pt = [1, 3, 2] assert intvp == IntervalProd(true_min_pt, true_max_pt) with pytest.raises(IndexError): intvp1.insert(3, intvp2) with pytest.raises(IndexError): intvp1.insert(-4, intvp2)
def test_dist(): set_ = IntervalProd(1, 2) for interior in [1.0, 1.1, 2.0]: assert set_.dist(interior) == 0.0 for exterior in [0.0, 2.0, np.inf]: assert set_.dist(exterior) == min(abs(set_.min_pt - exterior), abs(exterior - set_.max_pt)) assert set_.dist(np.NaN) == np.inf
def test_sub(): interv1 = Interval(1, 2) interv2 = Interval(3, 4) assert interv1 - 2.0 == Interval(-1, 0) assert interv1 - interv2 == Interval(-3, -1) interv1 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) interv2 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) assert interv1 - interv2 == IntervalProd([-1, -1, -1, -1, -1], [1, 1, 1, 1, 1])
def test_mul(): interv1 = Interval(1, 2) interv2 = Interval(3, 4) assert interv1 * 2.0 == Interval(2, 4) assert interv1 * interv2 == Interval(3, 8) interv1 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) interv2 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) assert interv1 * interv2 == IntervalProd([1, 4, 9, 16, 25], [4, 9, 16, 25, 36])
def test_max_pt(): set_ = IntervalProd(1, 2) assert almost_equal(set_.max_pt, 2) set_ = IntervalProd(0, np.inf) assert almost_equal(set_.max_pt, np.inf) set_ = IntervalProd([1], [2]) assert almost_equal(set_.max_pt, 2) set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.max_pt, [5, 6, 7])
def test_begin(): set_ = IntervalProd(1, 2) assert almost_equal(set_.begin, 1) set_ = IntervalProd(-np.inf, 0) assert almost_equal(set_.begin, -np.inf) set_ = IntervalProd([1], [2]) assert almost_equal(set_.begin, 1) set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.begin, [1, 2, 3])
def test_min_pt(): set_ = IntervalProd(1, 2) assert set_.min_pt == 1 set_ = IntervalProd(-np.inf, 0) assert set_.min_pt == -np.inf set_ = IntervalProd([1], [2]) assert set_.min_pt == 1 set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.min_pt, [1, 2, 3])
def test_end(): set_ = IntervalProd(1, 2) assert almost_equal(set_.end, 2) set_ = IntervalProd(0, np.inf) assert almost_equal(set_.end, np.inf) set_ = IntervalProd([1], [2]) assert almost_equal(set_.end, 2) set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.end, [5, 6, 7])
def test_min_pt(): set_ = IntervalProd(1, 2) assert almost_equal(set_.min_pt, 1) set_ = IntervalProd(-np.inf, 0) assert almost_equal(set_.min_pt, -np.inf) set_ = IntervalProd([1], [2]) assert almost_equal(set_.min_pt, 1) set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert all_equal(set_.min_pt, [1, 2, 3])
def test_add(): interv1 = Interval(1, 2) interv2 = Interval(3, 4) assert interv1 + 2.0 == Interval(3, 4) assert interv1 + interv2 == Interval(4, 6) interv1 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) interv2 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) assert interv1 + interv2 == IntervalProd([2, 4, 6, 8, 10], [4, 6, 8, 10, 12])
def test_element(): set_ = IntervalProd(1, 2) assert set_.element() in set_ set_ = IntervalProd(0, np.inf) assert set_.element() in set_ set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert set_.element() in set_
def test_contains(): set_ = IntervalProd(1, 2) assert 1 in set_ assert 2 in set_ assert 1.5 in set_ assert 3 not in set_ assert 'string' not in set_ assert [1, 2] not in set_ assert np.nan not in set_ positive_reals = IntervalProd(0, np.inf) assert 1 in positive_reals assert np.inf in positive_reals assert -np.inf not in positive_reals assert -1 not in positive_reals
def test_init(): IntervalProd(1, 2) IntervalProd(-np.inf, 2) IntervalProd(0, np.inf) IntervalProd([1], [2]) IntervalProd((1, ), (2, )) IntervalProd([1, 2, 3], [4, 5, 6]) IntervalProd((1, 2, 3), (4, 5, 6)) IntervalProd((1, 2, 3), (1, 2, 3)) with pytest.raises(ValueError): IntervalProd(2, 1) with pytest.raises(ValueError): IntervalProd((1, 2, 3), (1, 2, 0))
def test_div(): interv1 = Interval(1, 2) interv2 = Interval(3, 4) assert interv1 / 2.0 == Interval(1 / 2.0, 2 / 2.0) assert 2.0 / interv1 == Interval(2 / 2.0, 2 / 1.0) assert interv1 / interv2 == Interval(1 / 4.0, 2.0 / 3.0) interv_with_zero = Interval(-1, 1) with pytest.raises(ValueError): interv1 / interv_with_zero interv1 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) interv2 = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) quotient = IntervalProd([1 / 2., 2 / 3., 3 / 4., 4 / 5., 5 / 6.], [2 / 1., 3 / 2., 4 / 3., 5 / 4., 6 / 5.]) assert (interv1 / interv2).approx_equals(quotient, atol=1e-10)
def test_contains_set(): set_ = IntervalProd(1, 2) for sub_set in [np.array([1, 1.1, 1.2, 1.3, 1.4]), IntervalProd(1.2, 2), IntervalProd(1, 1.5), IntervalProd(1.2, 1.2)]: assert set_.contains_set(sub_set) for non_sub_set in [np.array([0, 1, 1.1, 1.2, 1.3, 1.4]), np.array([np.nan, 1.1, 1.3]), IntervalProd(1.2, 3), IntervalProd(0, 1.5), IntervalProd(3, 4)]: assert not set_.contains_set(non_sub_set) for non_set in [1, [1, 2], {'hello': 1.0}]: with pytest.raises(AttributeError): set_.contains_set(non_set)
def uniform_sampling(begin, end, num_nodes, nodes_on_bdry=True): """Sample an implicitly defined interval product uniformly. Parameters ---------- begin : `array-like` or `float` The lower ends of the intervals in the product end : `array-like` or `float` The upper ends of the intervals in the product num_nodes : `int` or `tuple` of `int` Number of nodes per axis. For dimension >= 2, a `tuple` is required. All entries must be positive. Entries corresponding to degenerate axes must be equal to 1. nodes_on_bdry : `bool` or `sequence`, optional If a sequence is provided, it determines per axis whether to place the last grid point on the boundary (True) or shift it by half a cell size into the interior (False). In each axis, an entry may consist in a single `bool` or a 2-tuple of `bool`. In the latter case, the first tuple entry decides for the left, the second for the right boundary. The length of the sequence must be ``array.ndim``. A single boolean is interpreted as a global choice for all boundaries. See also -------- uniform_sampling_fromintv : sample a given interval product odl.discr.partition.uniform_partition : divide implicitly defined interval product into equally sized subsets Examples -------- >>> grid = uniform_sampling([-1.5, 2], [-0.5, 3], (3, 3)) >>> grid.coord_vectors (array([-1.5, -1. , -0.5]), array([ 2. , 2.5, 3. ])) To have the nodes in the "middle", use nodes_on_bdry=False >>> grid = uniform_sampling([-1.5, 2], [-0.5, 3], (2, 2), ... nodes_on_bdry=False) >>> grid.coord_vectors (array([-1.25, -0.75]), array([ 2.25, 2.75])) """ return uniform_sampling_fromintv(IntervalProd(begin, end), num_nodes, nodes_on_bdry=nodes_on_bdry)
def convex_hull(self): """Return the smallest `IntervalProd` containing this grid. The convex hull of a set is the union of all line segments between points in the set. For a tensor grid, it is the interval product given by the extremal coordinates. Returns ------- chull : `IntervalProd` Interval product defined by the minimum and maximum of the grid Examples -------- >>> g = TensorGrid([-1, 0, 3], [2, 4], [5], [2, 4, 7]) >>> g.convex_hull() IntervalProd([-1.0, 2.0, 5.0, 2.0], [3.0, 4.0, 5.0, 7.0]) """ return IntervalProd(self.min(), self.max())
def test_extent(): set_ = IntervalProd(1, 2) assert set_.extent == 1 set_ = IntervalProd(1, 1) assert set_.extent == 0 set_ = IntervalProd(0, np.inf) assert set_.extent == np.inf set_ = IntervalProd(-np.inf, 0) assert set_.extent == np.inf set_ = IntervalProd(-np.inf, np.inf) assert set_.extent == np.inf set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert list(set_.extent) == [4, 4, 4]
def test_true_ndim(): set_ = IntervalProd(1, 2) assert set_.true_ndim == 1 set_ = IntervalProd(1, 1) assert set_.true_ndim == 0 set_ = IntervalProd(0, np.inf) assert set_.true_ndim == 1 set_ = IntervalProd([1], [2]) assert set_.true_ndim == 1 set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert set_.true_ndim == 3 set_ = IntervalProd([1, 2, 3], [1, 6, 7]) assert set_.true_ndim == 2
def uniform_partition(begin=None, end=None, num_nodes=None, cell_sides=None, nodes_on_bdry=False): """Return a partition with equally sized cells. Parameters ---------- begin, end : float or array-like, optional Vectors defining the begin end end points of an `IntervalProd` (a rectangular box). For one-dimensional partitions, single floats can be provided. ``None`` entries mean "compute the value". num_nodes : int or sequence of int, optional Number of nodes per axis. For 1d intervals, a single integer can be specified. ``None`` entries mean "compute the value". cell_sides : float or array-like, optional Side length of the partition cells per axis. For 1d intervals, a single integer can be specified. ``None`` entries mean "compute the value". nodes_on_bdry : `bool` or `sequence`, optional If a sequence is provided, it determines per axis whether to place the last grid point on the boundary (True) or shift it by half a cell size into the interior (False). In each axis, an entry may consist in a single `bool` or a 2-tuple of `bool`. In the latter case, the first tuple entry decides for the left, the second for the right boundary. The length of the sequence must be ``array.ndim``. A single boolean is interpreted as a global choice for all boundaries. Notes ----- In each axis, 3 of the 4 possible parameters ``begin``, ``end``, ``num_nodes`` and ``cell_sides`` must be given. If all four are provided, they are checked for consistency. See also -------- uniform_partition_fromintv : partition an existing set uniform_partition_fromgrid : use an existing grid as basis Examples -------- Any combination of three of the four parameters can be used for creation of a partition: >>> part = uniform_partition(begin=0, end=2, num_nodes=4) >>> part.cell_boundary_vecs (array([ 0. , 0.5, 1. , 1.5, 2. ]),) >>> part = uniform_partition(begin=0, num_nodes=4, cell_sides=0.5) >>> part.cell_boundary_vecs (array([ 0. , 0.5, 1. , 1.5, 2. ]),) >>> part = uniform_partition(end=2, num_nodes=4, cell_sides=0.5) >>> part.cell_boundary_vecs (array([ 0. , 0.5, 1. , 1.5, 2. ]),) >>> part = uniform_partition(begin=0, end=2, cell_sides=0.5) >>> part.cell_boundary_vecs (array([ 0. , 0.5, 1. , 1.5, 2. ]),) In higher dimensions, the parameters can be given differently in each axis. Where None is given, the value will be computed: >>> part = uniform_partition(begin=[0, 0], end=[1, 2], ... num_nodes=[4, 2]) >>> part.cell_boundary_vecs (array([ 0. , 0.25, 0.5 , 0.75, 1. ]), array([ 0., 1., 2.])) >>> part = uniform_partition(begin=[0, 0], end=[1, 2], ... num_nodes=[None, 2], ... cell_sides=[0.25, None]) >>> part.cell_boundary_vecs (array([ 0. , 0.25, 0.5 , 0.75, 1. ]), array([ 0., 1., 2.])) >>> part = uniform_partition(begin=[0, None], end=[None, 2], ... num_nodes=[4, 2], ... cell_sides=[0.25, 1]) >>> part.cell_boundary_vecs (array([ 0. , 0.25, 0.5 , 0.75, 1. ]), array([ 0., 1., 2.])) By default, no grid points are placed on the boundary: >>> part = uniform_partition(0, 1, 4) >>> part.cell_boundary_vecs (array([ 0. , 0.25, 0.5 , 0.75, 1. ]),) >>> part.grid.coord_vectors (array([ 0.125, 0.375, 0.625, 0.875]),) This can be changed with the nodes_on_bdry parameter: >>> part = uniform_partition(0, 1, 3, nodes_on_bdry=True) >>> part.cell_boundary_vecs (array([ 0. , 0.25, 0.75, 1. ]),) >>> part.grid.coord_vectors (array([ 0. , 0.5, 1. ]),) We can specify this per axis, too. In this case we choose both in the first axis and only the rightmost in the second: >>> part = uniform_partition([0, 0], [1, 1], (3, 3), ... nodes_on_bdry=(True, (False, True))) ... >>> part.cell_boundary_vecs[0] # first axis, as above array([ 0. , 0.25, 0.75, 1. ]) >>> part.grid.coord_vectors[0] array([ 0. , 0.5, 1. ]) >>> part.cell_boundary_vecs[1] # second, asymmetric axis array([ 0. , 0.4, 0.8, 1. ]) >>> part.grid.coord_vectors[1] array([ 0.2, 0.6, 1. ]) """ # Normalize partition parameters # np.size(None) == 1 sizes = [np.size(p) for p in (begin, end, num_nodes, cell_sides)] ndim = int(np.max(sizes)) if ndim == 1: begin = [begin] end = [end] num_nodes = [num_nodes] cell_sides = [cell_sides] else: if begin is None: begin = [None] * ndim if end is None: end = [None] * ndim if num_nodes is None: num_nodes = [None] * ndim if cell_sides is None: cell_sides = [None] * ndim begin = list(begin) end = list(end) num_nodes = list(num_nodes) cell_sides = list(cell_sides) sizes = [len(p) for p in (begin, end, num_nodes, cell_sides)] if not all(s == ndim for s in sizes): raise ValueError('inconsistent sizes {}, {}, {}, {} of ' 'arguments `begin`, `end`, `num_nodes`, ' '`cell_sides`'.format(*sizes)) # Normalize nodes_on_bdry if np.shape(nodes_on_bdry) == (): nodes_on_bdry = ([(bool(nodes_on_bdry), bool(nodes_on_bdry))] * ndim) elif ndim == 1 and len(nodes_on_bdry) == 2: nodes_on_bdry = [nodes_on_bdry] elif len(nodes_on_bdry) != ndim: raise ValueError('nodes_on_bdry has length {}, expected {}.' ''.format(len(nodes_on_bdry), ndim)) # Calculate the missing parameters in begin, end, num_nodes for i, (b, e, n, s, on_bdry) in enumerate( zip(begin, end, num_nodes, cell_sides, nodes_on_bdry)): num_params = sum(p is not None for p in (b, e, n, s)) if num_params < 3: raise ValueError('in axis {}: expected at least 3 of the ' 'parameters `begin`, `end`, `num_nodes`, ' '`cell_sides`, got {}' ''.format(i, num_params)) # Unpack the tuple if possible, else use bool globally for this axis try: bdry_l, bdry_r = on_bdry except TypeError: bdry_l = bdry_r = on_bdry # For each node on the boundary, we subtract 1/2 from the number of # full cells between begin and end. if b is None: begin[i] = e - (n - sum([bdry_l, bdry_r]) / 2.0) * s elif e is None: end[i] = b + (n - sum([bdry_l, bdry_r]) / 2.0) * s elif n is None: # Here we add to n since (e-b)/s gives the reduced number of cells. n_calc = (e - b) / s + sum([bdry_l, bdry_r]) / 2.0 n_round = int(round(n_calc)) if abs(n_calc - n_round) > 1e-5: raise ValueError('in axis {}: calculated number of nodes ' '{} = ({} - {}) / {} too far from integer' ''.format(i, n_calc, e, b, s)) num_nodes[i] = n_round elif s is None: pass else: e_calc = b + (n - sum([bdry_l, bdry_r]) / 2.0) * s if not np.isclose(e, e_calc): raise ValueError('in axis {}: calculated endpoint ' '{} = {} + {} * {} too far from given ' 'endpoint {}.' ''.format(i, e_calc, b, n, s, e)) return uniform_partition_fromintv(IntervalProd(begin, end), num_nodes, nodes_on_bdry)
def test_contains_set(): set_ = IntervalProd(1, 2) for sub_set in [ np.array([1, 1.1, 1.2, 1.3, 1.4]), IntervalProd(1.2, 2), IntervalProd(1, 1.5), IntervalProd(1.2, 1.2) ]: assert set_.contains_set(sub_set) for non_sub_set in [ np.array([0, 1, 1.1, 1.2, 1.3, 1.4]), np.array([np.nan, 1.1, 1.3]), IntervalProd(1.2, 3), IntervalProd(0, 1.5), IntervalProd(3, 4) ]: assert not set_.contains_set(non_sub_set) for non_set in [1, [1, 2], {'hello': 1.0}]: with pytest.raises(AttributeError): set_.contains_set(non_set)
def test_extent(): set_ = IntervalProd(1, 2) assert set_.extent() == 1 set_ = IntervalProd(1, 1) assert set_.extent() == 0 set_ = IntervalProd(0, np.inf) assert set_.extent() == np.inf set_ = IntervalProd(-np.inf, 0) assert set_.extent() == np.inf set_ = IntervalProd(-np.inf, np.inf) assert set_.extent() == np.inf set_ = IntervalProd([1, 2, 3], [5, 6, 7]) assert list(set_.extent()) == [4, 4, 4]
def test_rectangle_area(): set_ = IntervalProd([1, 2], [3, 4]) assert set_.area == set_.volume assert set_.area == (3 - 1) * (4 - 2)
def test_interval_length(): set_ = IntervalProd(1, 2) assert set_.length == set_.volume assert set_.length == 1
def test_pos(): interv = IntervalProd(1, 2) assert +interv == interv interv = IntervalProd([1, 2, 3, 4, 5], [2, 3, 4, 5, 6]) assert +interv == interv