def test_lex_big(): criteria = [(0, 1, 2)] * 3 alts = [ # I think I got these items from a paper, but now I've forgotten # which. D'oh. (0, 1, 1), (1, 1, 0), (2, 0, 1), (0, 2, 0), (1, 0, 2), (2, 1, 1), (2, 1, 0), (2, 2, 0), (1, 0, 1) ] def p(find_best, max_dev, a): return vda(criteria=criteria, alts=alts, asker=a, find_best=find_best, max_dev=max_dev) prefs = p(1, 3, lambda a, b: Relation.cmp(a[::-1], b[::-1])) assert prefs.maxes() == {(2, 2, 2)} assert prefs.maxes(among=alts) == {(1, 0, 2)} prefs = p(1, 3, lambda a, b: Relation.cmp(a, b)) assert prefs.maxes() == {(2, 2, 2)} assert prefs.maxes(among=alts) == {(2, 2, 0)} prefs = p(3, 4, lambda a, b: Relation.cmp(a, b)) assert prefs.extreme(3, among=alts) == {(2, 2, 0), (2, 1, 1), (2, 1, 0)}
def test_simple_strings(): criteria = [['bad', 'good'], ['expensive', 'cheap']] alts = [('bad', 'cheap'), ('good', 'expensive'), ('bad', 'expensive')] def asker(a, b): # We prefer good to bad, but when that criterion is the same, # we prefer cheap to expensive. if a[0] == b[0]: if a[1] == b[1]: return EQ elif a[1] == 'cheap': return GT else: return LT elif a[0] == 'good': return GT else: return LT for find_best in (1, 2, None): prefs = vda(criteria=criteria, alts=alts if find_best else None, asker=asker, find_best=find_best) assert prefs.maxes(among=alts) == {('good', 'expensive')} if find_best == 2: assert prefs.extreme(2, among=alts) == {('good', 'expensive'), ('bad', 'cheap')} elif not find_best: assert prefs.maxes() == {('good', 'cheap')} ranking = (('bad', 'expensive'), ('bad', 'cheap'), ('good', 'expensive'), ('good', 'cheap')) for (ai, a), (bi, b) in choose2(enumerate(ranking)): assert prefs.cmp(a, b) == Relation.cmp(ai, bi)
def test_appendixD(): '''Appendix D of Larichev and Moshkovich (1995).''' criteria = [(3, 2, 1)] * 3 # 3 is worst and 1 is best. alts = [(1, 2, 3), (2, 3, 1), (3, 1, 2)] dm_ranking = [(2, 1, 1), (1, 1, 2), (1, 2, 1), (1, 3, 1), (3, 1, 1), (1, 1, 3)] # The first element is the best, so we negate `cmp` in the # asker. def asker(a, b): return -Relation.cmp(dm_ranking.index(a), dm_ranking.index(b)) Proposal1, Proposal2, Proposal3 = alts for goal in ('find_best', 'rank_alts', 'rank_space'): prefs = vda(criteria=criteria, alts=(None if goal == 'rank_alts' else alts), asker=asker, find_best=goal == 'find_best' and 1) assert prefs.maxes(among=alts) == {Proposal2} if goal == 'rank_alts': for v1, v2 in choose2(dm_ranking): assert prefs.cmp(v1, v2) == -Relation.cmp( dm_ranking.index(v1), dm_ranking.index(v2)) if goal != 'find_best': assert prefs.cmp(Proposal2, Proposal1) == GT assert prefs.cmp(Proposal2, Proposal3) == GT assert prefs.cmp(Proposal3, Proposal1) == GT
def test_lex_generalized(criteria, R, n_questions=(15, 34, 33, 35, 30, 75, 86, 463)): '''Artiruno should be able to reproduce lexicographic preferences, in which the criteria have a defined order of importance.''' criterion_order = R.sample(range(len(criteria)), len(criteria)) return lambda a, b: Relation.cmp(*(tuple(v[i] for i in criterion_order) for v in (a, b)))
def test_value_function(criteria, R, n_questions=(15, 34, 53, 35, 33, 86, 76, 652)): '''Artiruno should be able to reproduce preferences defined by an additive value function, in which each criterion increment adds a certain positive amount of utility.''' values = tuple( tuple(0 if i == 0 else R.randint(1, 4) for i in range(len(c))) for c in criteria) return lambda a, b: Relation.cmp(*(sum( sum(values[ci][:cl + 1]) for ci, cl in enumerate(item)) for item in (a, b)))
def test_extreme_n(): x = PreorderedSet(l + str(i) for l in "wxyz" for i in range(3)) for a, b in choose2(x.elements): x.learn(a, b, Relation.cmp(a[0], b[0])) assert (x.maxes() == x.extreme(2) == x.extreme(3) == {"z0", "z1", "z2"}) assert (x.extreme(4) == x.extreme(5) == x.extreme(6) == {"z0", "z1", "z2", "y0", "y1", "y2"}) def xb(n): return x.extreme(n, bottom = True) assert (x.mins() == xb(2) == xb(3) == {"w0", "w1", "w2"}) assert (xb(4) == xb(5) == xb(6) == {"w0", "w1", "w2", "x0", "x1", "x2"})
def asker(a, b): return -Relation.cmp(dm_ranking.index(a), dm_ranking.index(b))
def test_lex_small(): 'A scenario with lexicographic preferences.' criteria = [(0, 1)] * 3 alts = [(1, 0, 0), (0, 1, 1)] prefs = vda(criteria=criteria, alts=alts, asker=Relation.cmp, max_dev=3) assert prefs.cmp(*alts) == Relation.cmp(*alts)
async def asker(a, b): l.append('start') queue.put_nowait(1) await queue.join() l.append('done') return Relation.cmp(a, b)