# imports from src.topupopt.problems.esipp.resource import ResourcePrice from src.topupopt.problems.esipp.resource import are_prices_time_invariant # ***************************************************************************** # ***************************************************************************** class TestResourcePrice: # ************************************************************************* # ************************************************************************* def test_resources_time_invariant(self): # single entry resource_prices = { (0, 0, 0): ResourcePrice(prices=1, volumes=None), } assert are_prices_time_invariant(resource_prices) # ********************************************************************* # single assessment, two periods, same prices for both periods resource_prices = { (0, 0, 0): ResourcePrice(prices=1, volumes=None), (0, 0, 1): ResourcePrice(prices=1, volumes=None), (0, 0, 2): ResourcePrice(prices=1, volumes=None), (0, 1, 0): ResourcePrice(prices=1, volumes=None), (0, 1, 1): ResourcePrice(prices=1, volumes=None), (0, 1, 2): ResourcePrice(prices=1, volumes=None), } assert are_prices_time_invariant(resource_prices) # ********************************************************************* # single assessment, two periods, same prices per period resource_prices = { (0, 0, 0): ResourcePrice(prices=1, volumes=None), (0, 0, 1): ResourcePrice(prices=1, volumes=None), (0, 0, 2): ResourcePrice(prices=1, volumes=None), (0, 1, 0): ResourcePrice(prices=2, volumes=None), (0, 1, 1): ResourcePrice(prices=2, volumes=None), (0, 1, 2): ResourcePrice(prices=2, volumes=None), } assert are_prices_time_invariant(resource_prices) # ********************************************************************* # single assessment, two periods, different prices in a given period resource_prices = { (0, 0, 0): ResourcePrice(prices=1, volumes=None), (0, 0, 1): ResourcePrice(prices=1, volumes=None), (0, 0, 2): ResourcePrice(prices=1, volumes=None), (0, 1, 0): ResourcePrice(prices=2, volumes=None), (0, 1, 1): ResourcePrice(prices=2.5, volumes=None), (0, 1, 2): ResourcePrice(prices=2, volumes=None), } assert not are_prices_time_invariant(resource_prices) # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_resource_prices_reals(self): # 1) single segment, no volume limit, real input prices = 3 volumes = None res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=False) == 1 assert res_p.number_segments(redo=True) == 1 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # 2) single segment, volume limit, real input prices = 3 volumes = 1.5 res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=False) == 1 assert res_p.number_segments(redo=True) == 1 assert res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ************************************************************************* # ************************************************************************* def test_equivalence_single(self): # ********************************************************************* # ********************************************************************* # single segment # ********************************************************************* # ********************************************************************* # no volume limit # single segment, no volume limit, different formats # prices and volumes match = True prices = 3 volumes = None res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices], volumes=[volumes]) assert res_p1 == res_p2 assert res_p2 == res_p1 # ********************************************************************* # single segment, no volume limit, different formats # prices do not match = False prices = 3 volumes = None res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices + 1], volumes=[volumes]) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, no volume limit, same format # prices and volumes match = True prices = 3 volumes = None res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert res_p1 == res_p2 assert res_p2 == res_p1 # ********************************************************************* # single segment, no volume limit, same format # prices do not match = False prices = 3 volumes = None res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices + 1, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # ********************************************************************* # with volume limits # single segment, volume limit, different formats # prices and volumes match = True prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices], volumes=[volumes]) assert res_p1 == res_p2 assert res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, different formats: False # prices do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices + 1], volumes=[volumes]) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, same format # prices and volumes match = True prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert res_p1 == res_p2 assert res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, same format: False # prices do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices + 1, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, different formats # volumes do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices], volumes=[volumes + 1]) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, same format # volumes do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=volumes + 1) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, different formats # volumes do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=[prices], volumes=[None]) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # single segment, volume limit, same format # volumes do not match = False prices = 3 volumes = 1 res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=None) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_equivalence_multiple_segments(self): # ********************************************************************* # ********************************************************************* # multiple segments # ********************************************************************* # ********************************************************************* # no volume limit # two segments, no volume limit, same format # prices and volumes match = True prices = [1, 3] volumes = [1, None] res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert res_p1 == res_p2 assert res_p2 == res_p1 # two segments, no volume limit, same format # prices do not match = False prices = [1, 3] volumes = [1, None] res_p1 = ResourcePrice(prices=prices, volumes=volumes) prices = [2, 3] volumes = [1, None] res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # with volume limits # two segments segment, volume limit, same format # prices and volumes match = True prices = [1, 3] volumes = [1, 3] res_p1 = ResourcePrice(prices=prices, volumes=volumes) res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert res_p1 == res_p2 assert res_p2 == res_p1 # two segments, volume limit, same format: False # prices do not match = False prices = [1, 3] volumes = [1, 4] res_p1 = ResourcePrice(prices=prices, volumes=volumes) prices = [1, 4] volumes = [1, 4] res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # volumes do not match # single segment, volume limit, same format # volumes do not match = False prices = [1, 3] volumes = [1, 4] res_p1 = ResourcePrice(prices=prices, volumes=volumes) prices = [1, 3] volumes = [1, 5] res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # single segment, volume limit, same format # volumes do not match = False prices = [1, 3] volumes = [1, 4] res_p1 = ResourcePrice(prices=prices, volumes=volumes) prices = [1, 3] volumes = [1, None] res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # ********************************************************************* # different number of segments prices = [1, 3] volumes = [1, 4] res_p1 = ResourcePrice(prices=prices, volumes=volumes) prices = [1, 3, 5] volumes = [1, 4, None] res_p2 = ResourcePrice(prices=prices, volumes=volumes) assert not res_p1 == res_p2 assert not res_p2 == res_p1 # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_resource_prices_lists(self): # ********************************************************************* # aspects that were tested: # i) number of segments (1, multiple or none) # ii) price variations (increasing, decreasing and stable) # iii) volume limits # ********************************************************************* # 1) multiple segments, prices increase, volume limits # 2) multiple segments, prices decrease, volume limits # 3) multiple segments, prices are stable, volume limits # 4) multiple segments, prices increase, no volume limit # 5) multiple segments, prices decrease, no volume limit # 6) multiple segments, prices are stable, no volume limit # 7) one segment, prices are stable, volume limits # 8) one segment, prices are stable, no volume limit # ********************************************************************* # 1) multiple segments, prices increase, volume limits prices = [1, 2, 3] volumes = [2, 1, 3] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 3 assert res_p.number_segments(redo=False) == 3 assert res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert not res_p.price_monotonically_decreasing_with_volume() assert not res_p.is_volume_invariant() # ********************************************************************* # 2) multiple segments, prices decrease, volume limits prices = [3, 2, 1] volumes = [2, 1, 3] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=False) == 3 assert res_p.is_volume_capped() assert not res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert not res_p.is_volume_invariant() # ********************************************************************* # 3) multiple segments, prices are stable, volume limits prices = [2, 2, 2] volumes = [2, 1, 3] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 3 assert res_p.number_segments(redo=False) == 3 assert res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ********************************************************************* # 4) multiple segments, prices increase, no volume limit prices = [1, 2, 3] volumes = [2, 1, None] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 3 assert res_p.number_segments(redo=False) == 3 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert not res_p.price_monotonically_decreasing_with_volume() assert not res_p.is_volume_invariant() # ********************************************************************* # 5) multiple segments, prices decrease, no volume limit prices = [2, 2, 2] volumes = [2, 1, None] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 3 assert res_p.number_segments(redo=False) == 3 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ********************************************************************* # 6) multiple segments, prices are stable, no volume limit prices = [2, 2, 2] volumes = [2, 1, None] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 3 assert res_p.number_segments(redo=False) == 3 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ********************************************************************* # 7) one segment, prices are stable, volume limits prices = [2] volumes = [2] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 1 assert res_p.number_segments(redo=False) == 1 assert res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ********************************************************************* # 8) one segment, prices are stable, no volume limit prices = [3] volumes = [None] res_p = ResourcePrice(prices=prices, volumes=volumes) assert res_p.number_segments(redo=True) == 1 assert res_p.number_segments(redo=False) == 1 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() res_p = ResourcePrice(prices=prices[0], volumes=volumes[0]) assert res_p.number_segments(redo=True) == 1 assert res_p.number_segments(redo=False) == 1 assert not res_p.is_volume_capped() assert res_p.price_monotonically_increasing_with_volume() assert res_p.price_monotonically_decreasing_with_volume() assert res_p.is_volume_invariant() # ********************************************************************* # errors # ********************************************************************* # create object without prices error_raised = False try: _ = ResourcePrice(prices=None, volumes=volumes) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with negative prices in lists error_raised = False try: _ = ResourcePrice(prices=[7, -3, 2], volumes=[3, 4, 5]) except ValueError: error_raised = True assert error_raised # ********************************************************************* # create object where an intermediate segment has no volume limit error_raised = False try: _ = ResourcePrice(prices=[7, 4, 2], volumes=[3, None, 5]) except ValueError: error_raised = True assert error_raised # ********************************************************************* # create object with negative volumes in lists error_raised = False try: _ = ResourcePrice(prices=[7, 3, 2], volumes=[4, -1, 2]) except ValueError: error_raised = True assert error_raised # ********************************************************************* # create object with non-numeric prices in lists error_raised = False try: _ = ResourcePrice(prices=[7, "4", 2], volumes=[3, 4, 5]) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with non-numeric volumes in lists error_raised = False try: _ = ResourcePrice(prices=[7, 3, 2], volumes=[4, "3", 2]) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with mismatched price and volume lists error_raised = False try: _ = ResourcePrice(prices=[7, 3, 2], volumes=[5, 7]) except ValueError: error_raised = True assert error_raised # ********************************************************************* # create object with a price list as an input and an unsupported type error_raised = False try: _ = ResourcePrice(prices=[7, 3, 2], volumes="hello") except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with negative prices in lists (no volumes are provided) error_raised = False try: _ = ResourcePrice(prices=[7, 3, -2], volumes=None) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with non-numeric prices in lists (no volumes are provided) error_raised = False try: _ = ResourcePrice(prices=[7, 3, "a"], volumes=None) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with non-numeric prices in lists (no volumes are provided) error_raised = False try: _ = ResourcePrice(prices=5, volumes=[7, 3, 4]) except TypeError: error_raised = True assert error_raised # ********************************************************************* # create object with negative prices error_raised = False try: _ = ResourcePrice(prices=-3, volumes=None) except ValueError: error_raised = True assert error_raised # ********************************************************************* # ***************************************************************************** # *****************************************************************************