Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
|
|
@ -0,0 +1,259 @@
|
|||
'''Diversity prediction theorem'''
|
||||
|
||||
from itertools import chain
|
||||
from functools import reduce
|
||||
|
||||
|
||||
# diversityValues :: Num a => a -> [a] ->
|
||||
# { mean-Error :: a, crowd-error :: a, diversity :: a }
|
||||
def diversityValues(x):
|
||||
'''The mean error, crowd error and
|
||||
diversity, for a given observation x
|
||||
and a non-empty list of predictions ps.
|
||||
'''
|
||||
def go(ps):
|
||||
mp = mean(ps)
|
||||
return {
|
||||
'mean-error': meanErrorSquared(x)(ps),
|
||||
'crowd-error': pow(x - mp, 2),
|
||||
'diversity': meanErrorSquared(mp)(ps)
|
||||
}
|
||||
return go
|
||||
|
||||
|
||||
# meanErrorSquared :: Num -> [Num] -> Num
|
||||
def meanErrorSquared(x):
|
||||
'''The mean of the squared differences
|
||||
between the observed value x and
|
||||
a non-empty list of predictions ps.
|
||||
'''
|
||||
def go(ps):
|
||||
return mean([
|
||||
pow(p - x, 2) for p in ps
|
||||
])
|
||||
return go
|
||||
|
||||
|
||||
# ------------------------- TEST -------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Observed value: 49,
|
||||
prediction lists: various.
|
||||
'''
|
||||
|
||||
print(unlines(map(
|
||||
showDiversityValues(49),
|
||||
[
|
||||
[48, 47, 51],
|
||||
[48, 47, 51, 42],
|
||||
[50, '?', 50, {}, 50], # Non-numeric values.
|
||||
[] # Missing predictions.
|
||||
]
|
||||
)))
|
||||
print(unlines(map(
|
||||
showDiversityValues('49'), # String in place of number.
|
||||
[
|
||||
[50, 50, 50],
|
||||
[40, 35, 40],
|
||||
]
|
||||
)))
|
||||
|
||||
|
||||
# ---------------------- FORMATTING ----------------------
|
||||
|
||||
# showDiversityValues :: Num -> [Num] -> Either String String
|
||||
def showDiversityValues(x):
|
||||
'''Formatted string representation
|
||||
of diversity values for a given
|
||||
observation x and a non-empty
|
||||
list of predictions p.
|
||||
'''
|
||||
def go(ps):
|
||||
def showDict(dct):
|
||||
w = 4 + max(map(len, dct.keys()))
|
||||
|
||||
def showKV(a, kv):
|
||||
k, v = kv
|
||||
return a + k.rjust(w, ' ') + (
|
||||
' : ' + showPrecision(3)(v) + '\n'
|
||||
)
|
||||
return 'Predictions: ' + showList(ps) + ' ->\n' + (
|
||||
reduce(showKV, dct.items(), '')
|
||||
)
|
||||
|
||||
def showProblem(e):
|
||||
return (
|
||||
unlines(map(indented(1), e)) if (
|
||||
isinstance(e, list)
|
||||
) else indented(1)(repr(e))
|
||||
) + '\n'
|
||||
|
||||
return 'Observation: ' + repr(x) + '\n' + (
|
||||
either(showProblem)(showDict)(
|
||||
bindLR(numLR(x))(
|
||||
lambda n: bindLR(numsLR(ps))(
|
||||
compose(Right, diversityValues(n))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
return go
|
||||
|
||||
|
||||
# ------------------ GENERIC FUNCTIONS -------------------
|
||||
|
||||
# Left :: a -> Either a b
|
||||
def Left(x):
|
||||
'''Constructor for an empty Either (option type) value
|
||||
with an associated string.
|
||||
'''
|
||||
return {'type': 'Either', 'Right': None, 'Left': x}
|
||||
|
||||
|
||||
# Right :: b -> Either a b
|
||||
def Right(x):
|
||||
'''Constructor for a populated Either (option type) value'''
|
||||
return {'type': 'Either', 'Left': None, 'Right': x}
|
||||
|
||||
|
||||
# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
|
||||
def bindLR(m):
|
||||
'''Either monad injection operator.
|
||||
Two computations sequentially composed,
|
||||
with any value produced by the first
|
||||
passed as an argument to the second.
|
||||
'''
|
||||
def go(mf):
|
||||
return (
|
||||
mf(m.get('Right')) if None is m.get('Left') else m
|
||||
)
|
||||
return go
|
||||
|
||||
|
||||
# compose :: ((a -> a), ...) -> (a -> a)
|
||||
def compose(*fs):
|
||||
'''Composition, from right to left,
|
||||
of a series of functions.
|
||||
'''
|
||||
def go(f, g):
|
||||
def fg(x):
|
||||
return f(g(x))
|
||||
return fg
|
||||
return reduce(go, fs, identity)
|
||||
|
||||
|
||||
# concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
def concatMap(f):
|
||||
'''A concatenated list over which a function has been mapped.
|
||||
The list monad can be derived by using a function f which
|
||||
wraps its output in a list,
|
||||
(using an empty list to represent computational failure).
|
||||
'''
|
||||
def go(xs):
|
||||
return chain.from_iterable(map(f, xs))
|
||||
return go
|
||||
|
||||
|
||||
# either :: (a -> c) -> (b -> c) -> Either a b -> c
|
||||
def either(fl):
|
||||
'''The application of fl to e if e is a Left value,
|
||||
or the application of fr to e if e is a Right value.
|
||||
'''
|
||||
return lambda fr: lambda e: fl(e['Left']) if (
|
||||
None is e['Right']
|
||||
) else fr(e['Right'])
|
||||
|
||||
|
||||
# identity :: a -> a
|
||||
def identity(x):
|
||||
'''The identity function.'''
|
||||
return x
|
||||
|
||||
|
||||
# indented :: Int -> String -> String
|
||||
def indented(n):
|
||||
'''String indented by n multiples
|
||||
of four spaces.
|
||||
'''
|
||||
return lambda s: (4 * ' ' * n) + s
|
||||
|
||||
# mean :: [Num] -> Float
|
||||
def mean(xs):
|
||||
'''Arithmetic mean of a list
|
||||
of numeric values.
|
||||
'''
|
||||
return sum(xs) / float(len(xs))
|
||||
|
||||
|
||||
# numLR :: a -> Either String Num
|
||||
def numLR(x):
|
||||
'''Either Right x if x is a float or int,
|
||||
or a Left explanatory message.'''
|
||||
return Right(x) if (
|
||||
isinstance(x, (float, int))
|
||||
) else Left(
|
||||
'Expected number, saw: ' + (
|
||||
str(type(x)) + ' ' + repr(x)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# numsLR :: [a] -> Either String [Num]
|
||||
def numsLR(xs):
|
||||
'''Either Right xs if all xs are float or int,
|
||||
or a Left explanatory message.'''
|
||||
def go(ns):
|
||||
ls, rs = partitionEithers(map(numLR, ns))
|
||||
return Left(ls) if ls else Right(rs)
|
||||
return bindLR(
|
||||
Right(xs) if (
|
||||
bool(xs) and isinstance(xs, list)
|
||||
) else Left(
|
||||
'Expected a non-empty list, saw: ' + (
|
||||
str(type(xs)) + ' ' + repr(xs)
|
||||
)
|
||||
)
|
||||
)(go)
|
||||
|
||||
|
||||
# partitionEithers :: [Either a b] -> ([a],[b])
|
||||
def partitionEithers(lrs):
|
||||
'''A list of Either values partitioned into a tuple
|
||||
of two lists, with all Left elements extracted
|
||||
into the first list, and Right elements
|
||||
extracted into the second list.
|
||||
'''
|
||||
def go(a, x):
|
||||
ls, rs = a
|
||||
r = x.get('Right')
|
||||
return (ls + [x.get('Left')], rs) if None is r else (
|
||||
ls, rs + [r]
|
||||
)
|
||||
return reduce(go, lrs, ([], []))
|
||||
|
||||
|
||||
# showList :: [a] -> String
|
||||
def showList(xs):
|
||||
'''Compact string representation of a list'''
|
||||
return '[' + ','.join(str(x) for x in xs) + ']'
|
||||
|
||||
|
||||
# showPrecision :: Int -> Float -> String
|
||||
def showPrecision(n):
|
||||
'''A string showing a floating point number
|
||||
at a given degree of precision.'''
|
||||
def go(x):
|
||||
return str(round(x, n))
|
||||
return go
|
||||
|
||||
|
||||
# unlines :: [String] -> String
|
||||
def unlines(xs):
|
||||
'''A single string derived by the intercalation
|
||||
of a list of strings with the newline character.'''
|
||||
return '\n'.join(xs)
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue