def calculate(self): item_splitter = SurplusMaximizer() result = item_splitter.split( \ [i.name for i in self.items.all()], \ [p.name for p in self.participants.all()], \ self.splitter_bids() \ ) return result
def setUp(self): self.splitter = SurplusMaximizer()
class TestSurplusMaximizer(unittest.TestCase): """ Test the Surplus Maximizer splitter """ def setUp(self): self.splitter = SurplusMaximizer() def test_single_identical_bid(self): """ Test when people bid the same thing on a single item This should theoretically not happen very frequently, but if it did we would expect the algo to cope with it """ bids = [Cost(ITEM1, ACTOR1, 1640), Cost(ITEM2, ACTOR1, 1540), Cost(ITEM3, ACTOR1, 1140), Cost(ITEM4, ACTOR1, 1640), Cost(ITEM5, ACTOR1, 1740), Cost(ITEM1, ACTOR2, 1540), Cost(ITEM2, ACTOR2, 1240), Cost(ITEM3, ACTOR2, 1340), Cost(ITEM4, ACTOR2, 1640), Cost(ITEM5, ACTOR2, 1940), Cost(ITEM1, ACTOR3, 1740), Cost(ITEM2, ACTOR3, 1540), Cost(ITEM3, ACTOR3, 1040), Cost(ITEM4, ACTOR3, 1640), Cost(ITEM5, ACTOR3, 1740), Cost(ITEM1, ACTOR4, 1440), Cost(ITEM2, ACTOR4, 1640), Cost(ITEM3, ACTOR4, 1240), Cost(ITEM4, ACTOR4, 1640), Cost(ITEM5, ACTOR4, 1740), Cost(ITEM1, ACTOR5, 1640), Cost(ITEM2, ACTOR5, 1640), Cost(ITEM3, ACTOR5, 1140), Cost(ITEM4, ACTOR5, 1640), Cost(ITEM5, ACTOR5, 1640)] result = self.splitter.split(ITEMS[:5], ACTORS[:5], bids) expected = [(ITEM1, ACTOR3, None), (ITEM2, ACTOR5, None), (ITEM3, ACTOR4, None), (ITEM4, ACTOR1, None), (ITEM5, ACTOR2, None)] item_assignments_present(self, result, expected) def test_obvious_auction(self): """ Test when people bid such that there is a "right" answer """ bids = [Cost(ITEM1, ACTOR1, 1000), Cost(ITEM2, ACTOR1, 1000), Cost(ITEM3, ACTOR1, 1000), Cost(ITEM4, ACTOR1, 5000), Cost(ITEM1, ACTOR2, 1000), Cost(ITEM2, ACTOR2, 1000), Cost(ITEM3, ACTOR2, 5000), Cost(ITEM4, ACTOR2, 1000), Cost(ITEM1, ACTOR3, 1000), Cost(ITEM2, ACTOR3, 5000), Cost(ITEM3, ACTOR3, 1000), Cost(ITEM4, ACTOR3, 1000), Cost(ITEM1, ACTOR4, 5000), Cost(ITEM2, ACTOR4, 1000), Cost(ITEM3, ACTOR4, 1000), Cost(ITEM4, ACTOR4, 1000)] result = self.splitter.split(ITEMS[:4], ACTORS[:4], bids) expected = [(ITEM1, ACTOR4, None), (ITEM2, ACTOR3, None), (ITEM3, ACTOR2, None), (ITEM4, ACTOR1, None)] item_assignments_present(self, result, expected) def test_reasonable_auction(self): """ Test a "real world" auction Each person has 5000 to use as they wish, on 5 items """ # I have no preferences bids = [Cost(ITEM1, ACTOR1, 1000), Cost(ITEM2, ACTOR1, 1000), Cost(ITEM3, ACTOR1, 1000), Cost(ITEM4, ACTOR1, 1000), Cost(ITEM5, ACTOR1, 1000), # I have linear preferences Cost(ITEM1, ACTOR2, 700), Cost(ITEM2, ACTOR2, 800), Cost(ITEM3, ACTOR2, 1000), Cost(ITEM4, ACTOR2, 1200), Cost(ITEM5, ACTOR2, 1300), # I have non-linear preferences Cost(ITEM1, ACTOR3, 400), Cost(ITEM2, ACTOR3, 800), Cost(ITEM3, ACTOR3, 1000), Cost(ITEM4, ACTOR3, 1200), Cost(ITEM5, ACTOR3, 1600), # I have arbitrary preference Cost(ITEM1, ACTOR4, 2435), Cost(ITEM2, ACTOR4, 305), Cost(ITEM3, ACTOR4, 310), Cost(ITEM4, ACTOR4, 1725), Cost(ITEM5, ACTOR4, 225), # I have strong preferences Cost(ITEM1, ACTOR5, 0), Cost(ITEM2, ACTOR5, 0), Cost(ITEM3, ACTOR5, 0), Cost(ITEM4, ACTOR5, 0), Cost(ITEM5, ACTOR5, 5000)] result = self.splitter.split(ITEMS[:5], ACTORS[:5], bids) expected = [(ITEM1, ACTOR4, None), (ITEM2, ACTOR1, None), (ITEM3, ACTOR3, None), (ITEM4, ACTOR2, None), (ITEM5, ACTOR5, None)] item_assignments_present(self, result, expected) def test_odd_items(self): """ Test an auction where we have more items than people """ # I have some preferences bids = [Cost(ITEM1, ACTOR1, 1000), Cost(ITEM2, ACTOR1, 1000), Cost(ITEM3, ACTOR1, 1000), Cost(ITEM4, ACTOR1, 0), Cost(ITEM5, ACTOR1, 2000), # I have other preferences Cost(ITEM1, ACTOR2, 0), Cost(ITEM2, ACTOR2, 1500), Cost(ITEM3, ACTOR2, 1500), Cost(ITEM4, ACTOR2, 500), Cost(ITEM5, ACTOR2, 1500)] result = self.splitter.split(ITEMS[:5], ACTORS[:2], bids) expected = [(ITEM1, ACTOR1, None), (ITEM2, ACTOR2, None), (ITEM3, ACTOR2, None), (ITEM4, ACTOR2, None), (ITEM5, ACTOR1, None)] item_assignments_present(self, result, expected) def test_normalize_equal(self): test_dict = { ITEM1: (ACTOR1, 1000), ITEM2: (ACTOR2, 500), ITEM3: (ACTOR3, 0), ITEM4: (ACTOR4, 2000) } total = 3500 expected = [(ITEM1, ACTOR1, 1000), (ITEM2, ACTOR2, 500), (ITEM3, ACTOR3, 0), (ITEM4, ACTOR4, 2000)] result = self.splitter.normalize(test_dict, total) item_assignments_present(self, result, expected) def test_normalize_high(self): test_dict = { ITEM1: (ACTOR1, 1000), ITEM2: (ACTOR2, 500), ITEM3: (ACTOR3, 0), ITEM4: (ACTOR4, 2000) } total = 1000 expected = [(ITEM1, ACTOR1, 286), (ITEM2, ACTOR2, 143), (ITEM3, ACTOR3, 0), (ITEM4, ACTOR4, 571)] result = self.splitter.normalize(test_dict, total) item_assignments_present(self, result, expected) def test_normalize_low(self): test_dict = { ITEM1: (ACTOR1, 1000), ITEM2: (ACTOR2, 500), ITEM3: (ACTOR3, 0), ITEM4: (ACTOR4, 2000) } total = 5000 expected = [(ITEM1, ACTOR1, 1429), (ITEM2, ACTOR2, 714), (ITEM3, ACTOR3, 0), (ITEM4, ACTOR4, 2857)] result = self.splitter.normalize(test_dict, total) item_assignments_present(self, result, expected)
def normalized(self): item_splitter = SurplusMaximizer() return item_splitter.normalize(self.calculate(), self.total_bid)