[81] | 1 | import unittest
|
---|
| 2 | from pyson.ObjectMapper import ObjectMapper
|
---|
| 3 | from geniusweb.bidspace.Interval import Interval
|
---|
| 4 | from decimal import Decimal
|
---|
| 5 | from geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace import LinearAdditiveUtilitySpace
|
---|
| 6 | import json
|
---|
| 7 | from geniusweb.profile.Profile import Profile
|
---|
| 8 | from geniusweb.bidspace.BidsWithUtility import BidsWithUtility
|
---|
| 9 | from random import randrange
|
---|
| 10 | from geniusweb.bidspace.AllBidsList import AllBidsList
|
---|
| 11 | import time
|
---|
| 12 | from pathlib import Path
|
---|
| 13 |
|
---|
| 14 | class BidsWithUtilityTest(unittest.TestCase):
|
---|
| 15 | jackson = ObjectMapper()
|
---|
| 16 | utilityGoal = Interval(Decimal("0.50"), Decimal("0.51"))
|
---|
| 17 | accuracy = 5
|
---|
| 18 |
|
---|
| 19 |
|
---|
| 20 | parameters=[
|
---|
| 21 | [ "test/resources/jobs/jobs1.json", 11 ],
|
---|
| 22 | [ "test/resources/7issues/7issues1.json", 260000 ],
|
---|
| 23 | [ "test/resources/9issues/9issues1.json", 25000000 ]
|
---|
| 24 | ]
|
---|
| 25 |
|
---|
| 26 | def testAll(self):
|
---|
| 27 | '''
|
---|
| 28 | runs all the tests. Python has no standard 'parameterized' mechanism
|
---|
| 29 | so we have to do it ourselves.
|
---|
| 30 | '''
|
---|
| 31 | for [filename, expectedsize] in self.parameters:
|
---|
| 32 | self.filename=filename
|
---|
| 33 | self.expectedSize= expectedsize
|
---|
| 34 | with self.subTest("test"+self.filename):
|
---|
| 35 | self.before()
|
---|
| 36 | self.simple()
|
---|
| 37 | with self.subTest("testMaxUtil"+self.filename):
|
---|
| 38 | self.before()
|
---|
| 39 | self.MaxUtil()
|
---|
| 40 | with self.subTest("benchmark"+self.filename):
|
---|
| 41 | self.before()
|
---|
| 42 | self.benchmark()
|
---|
| 43 |
|
---|
| 44 | def before(self):
|
---|
| 45 | print("Running from file " + self.filename)
|
---|
| 46 | file = Path(self.filename).read_text("utf-8")
|
---|
| 47 | self.profile = self.jackson.parse(json.loads(file), Profile)
|
---|
| 48 |
|
---|
| 49 |
|
---|
| 50 |
|
---|
| 51 | def simple(self):
|
---|
| 52 | '''
|
---|
| 53 | Test if the values are within acceptable range from the goal.
|
---|
| 54 | '''
|
---|
| 55 | list = BidsWithUtility.create(self.profile, self.accuracy).getBids(self.utilityGoal);
|
---|
| 56 | #check not all but only 10000 random bids as list may be way too large
|
---|
| 57 | #to test them all. Testing 1 billion bids may take 15 minutes or so on
|
---|
| 58 | #quad core i7 @2.4GHz.....
|
---|
| 59 | #also notice that we may be checking only part of the list if
|
---|
| 60 | #the size of the list would become bigger than maxint.
|
---|
| 61 | for n in range(10000):
|
---|
| 62 | bid = list.get(randrange(list.size()))
|
---|
| 63 | self.assertTrue(self.utilityGoal.contains(
|
---|
| 64 | round(self.profile.getUtility(bid),self.accuracy-1)),
|
---|
| 65 | "bid "+str(bid)+" is not in range "+str(self.utilityGoal))
|
---|
| 66 |
|
---|
| 67 | self.assertTrue(list.size()>= self.expectedSize)
|
---|
| 68 |
|
---|
| 69 | def MaxUtil(self) :
|
---|
| 70 | bidswithutil = BidsWithUtility.create(self.profile)
|
---|
| 71 | #notice, this is the *rounded* max util
|
---|
| 72 | maxutil = bidswithutil.getRange().getMax()
|
---|
| 73 | goal = Interval(maxutil - Decimal("0.00001"), maxutil)
|
---|
| 74 |
|
---|
| 75 | bidsnearmax = bidswithutil.getBids(goal)
|
---|
| 76 | self.assertTrue(bidsnearmax.size() != 0)
|
---|
| 77 |
|
---|
| 78 | foundmax = Decimal(0)
|
---|
| 79 | for bid in bidsnearmax :
|
---|
| 80 | util = self.profile.getUtility(bid)
|
---|
| 81 | if util>foundmax:
|
---|
| 82 | foundmax = util;
|
---|
| 83 | #found maximum may be slightly lower or higher because we rounded
|
---|
| 84 | #all weighted utilities.
|
---|
| 85 | self.assertTrue(abs(foundmax - maxutil) < 0.0001)
|
---|
| 86 |
|
---|
| 87 | def benchmark(self):
|
---|
| 88 | print("\nBenchmarking " + self.profile.getName());
|
---|
| 89 | domainsize = AllBidsList(self.profile.getDomain()).size()
|
---|
| 90 |
|
---|
| 91 | start = round(time.time()*1000)
|
---|
| 92 | body = BidsWithUtility.create(self.profile, self.accuracy)
|
---|
| 93 | list = body.getBids(self.utilityGoal)
|
---|
| 94 | end = round(time.time()*1000)
|
---|
| 95 | print("run time: " + str((end - start) / 1000.) + "s");
|
---|
| 96 | print("Total size of bidspace:" + str(domainsize))
|
---|
| 97 | print("Result size: " + str(list.size()))
|
---|