File size: 2,309 Bytes
952e1e7 7027070 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # SPDX-License-Identifier: MIT
"""Validate each native distribution, then average probabilities at equal weight."""
import math
def keys_for(q):
if q['type'] == 'choice':
return list(q['criteria'])
if q['type'] == 'score':
return [str(i) for i in range(len(q['criteria']))]
raise ValueError('unsupported question type ' + str(q['type']))
def distribution(q, answer):
if answer.get('type') != q['type']:
raise ValueError('native question type mismatch')
keys = keys_for(q)
probs = answer.get('probabilities', {})
if set(keys) != set(probs):
raise ValueError('native response dropped or added options')
values = {k: float(probs[k]) for k in keys}
if any(not math.isfinite(v) or not 0 <= v <= 1 for v in values.values()):
raise ValueError('invalid native option probability')
total = math.fsum(values.values())
if total <= 0 or abs(total - 1) > .01:
raise ValueError('native probabilities are not normalized')
return values
def mix(request, g, q):
questions = request['questions']
if set(g.get('answers', {})) != set(questions) or set(q.get('answers', {})) != set(questions):
raise ValueError('native question keys mismatch')
answers = {}
for qid, spec in questions.items():
x, y = g['answers'][qid], q['answers'][qid]
typ = spec['type']
answer = {'type': typ}
if typ == 'noul':
values = [float(a['noul']) for a in (x, y)]
if any(a.get('type') != typ for a in (x, y)) or any(not math.isfinite(v) or not 0 <= v <= 1 for v in values):
raise ValueError('invalid native noul probability')
answer['noul'] = .5 * (values[0] + values[1])
else:
px, py = distribution(spec, x), distribution(spec, y)
probs = {k: .5 * (px[k] + py[k]) for k in px}
total = math.fsum(probs.values())
probs = {k: v / total for k, v in probs.items()}
answer['probabilities'] = probs
if typ == 'choice':
answer['choice'] = max(sorted(probs), key=probs.get)
else:
answer['score'] = math.fsum(int(k) * v for k, v in probs.items())
answers[qid] = answer
return {'model': 'reax13', 'answers': answers}
|