Bases: improb.lowprev.LowPrev
An arbitrary finitely generated lower prevision, that is, a finite intersection of half-spaces, each of which constrains the set of probability mass functions.
This class is derived from collections.MutableMapping: keys are (gamble, event) pairs, values are (lprev, uprev) pairs:
>>> lpr = LowPoly(pspace='abcd', number_type='fraction')
>>> lpr[{'a': 2, 'b': 3}, 'abcd'] = ('1.5', '1.9')
>>> lpr[{'c': 1, 'd': 8}, 'cd'] = ('1.2', None)
>>> print(lpr)
a b c d
2 3 0 0 | a b c d : [3/2 , 19/10]
0 0 1 8 | c d : [6/5 , ]
Instead of working on the mapping directly, you can use the convenience methods set_lower(), set_upper(), and set_precise():
>>> lpr = LowPoly(pspace='abcd', number_type='fraction')
>>> lpr.set_lower({'a': 2, 'b': 3}, '1.5')
>>> lpr.set_upper({'a': 2, 'b': 3}, '1.9')
>>> lpr.set_lower({'c': 1, 'd': 8}, '1.2', event='cd')
>>> print(lpr)
a b c d
2 3 0 0 | a b c d : [3/2 , 19/10]
0 0 1 8 | c d : [6/5 , ]
Construct a polyhedral lower prevision on pspace.
Parameters: |
|
---|
Generally, you can pass a dict as a keyword argument in order to initialize the lower and upper previsions and/or probabilities:
>>> print(LowPoly(pspace=3, mapping={
... ((3, 1, 2), True): (1.5, None),
... ((1, 0, -1), (1, 2)): (0.25, 0.3)}))
0 1 2
3.0 1.0 2.0 | 0 1 2 : [1.5 , ]
1.0 0.0 -1.0 | 1 2 : [0.25, 0.3 ]
>>> print(LowPoly(pspace=3,
... lprev={(1, 3, 2): 1.5, (2, 0, -1): 1},
... uprev={(2, 0, -1): 1.9},
... prev={(9, 8, 20): 15},
... lprob={(1, 2): 0.2, (1,): 0.1},
... uprob={(1, 2): 0.3, (0,): 0.9},
... prob={(2,): '0.3'}))
0 1 2
0.0 0.0 1.0 | 0 1 2 : [0.3 , 0.3 ]
0.0 1.0 0.0 | 0 1 2 : [0.1 , ]
0.0 1.0 1.0 | 0 1 2 : [0.2 , 0.3 ]
1.0 0.0 0.0 | 0 1 2 : [ , 0.9 ]
1.0 3.0 2.0 | 0 1 2 : [1.5 , ]
2.0 0.0 -1.0 | 0 1 2 : [1.0 , 1.9 ]
9.0 8.0 20.0 | 0 1 2 : [15.0, 15.0]
A credal set can be specified simply as a list:
>>> print(LowPoly(pspace=3,
... credalset=[['0.1', '0.45', '0.45'],
... ['0.4', '0.3', '0.3'],
... ['0.3', '0.2', '0.5']]))
0 1 2
-10 10 0 | 0 1 2 : [-1, ]
-1 -2 0 | 0 1 2 : [-1, ]
1 1 1 | 0 1 2 : [1 , 1 ]
50/23 40/23 0 | 0 1 2 : [1 , ]
As a special case, for lower/upper/precise probabilities, if you need to set values on singletons, you can use a list instead of a dictionary:
>>> print(LowPoly(pspace='abc', lprob=['0.1', '0.2', '0.3']))
a b c
0 0 1 | a b c : [3/10, ]
0 1 0 | a b c : [1/5 , ]
1 0 0 | a b c : [1/10, ]
If the first argument is a LowPoly instance, then it is copied. For example:
>>> from improb.lowprev.lowprob import LowProb
>>> lpr = LowPoly(pspace='abc', lprob=['0.1', '0.1', '0.1'])
>>> print(lpr)
a b c
0 0 1 | a b c : [1/10, ]
0 1 0 | a b c : [1/10, ]
1 0 0 | a b c : [1/10, ]
>>> lprob = LowProb(lpr)
>>> print(lprob)
a : 1/10
b : 1/10
c : 1/10
Calculate coherent extension to the given keys (gamble/event pairs), using linear programming.
Parameters: |
|
---|
>>> pspace = PSpace('xyz')
>>> lpr = LowPoly(pspace=pspace, lprob=['0.1', '0.2', '0.15'], number_type='fraction')
>>> print(lpr)
x y z
0 0 1 | x y z : [3/20, ]
0 1 0 | x y z : [1/5 , ]
1 0 0 | x y z : [1/10, ]
>>> for event in pspace.subsets(empty=False):
... lpr.extend((subevent, event) for subevent in pspace.subsets(event))
>>> print(lpr)
x y z
0 0 0 | x y z : [0 , 0 ]
0 0 1 | x y z : [3/20 , 7/10 ]
0 1 0 | x y z : [1/5 , 3/4 ]
0 1 1 | x y z : [7/20 , 9/10 ]
1 0 0 | x y z : [1/10 , 13/20]
1 0 1 | x y z : [1/4 , 4/5 ]
1 1 0 | x y z : [3/10 , 17/20]
1 1 1 | x y z : [1 , 1 ]
0 0 0 | x y : [0 , 0 ]
0 1 0 | x y : [4/17 , 15/17]
1 0 0 | x y : [2/17 , 13/17]
1 1 0 | x y : [1 , 1 ]
0 0 0 | x z : [0 , 0 ]
0 0 1 | x z : [3/16 , 7/8 ]
1 0 0 | x z : [1/8 , 13/16]
1 0 1 | x z : [1 , 1 ]
0 0 0 | x : [0 , 0 ]
1 0 0 | x : [1 , 1 ]
0 0 0 | y z : [0 , 0 ]
0 0 1 | y z : [1/6 , 7/9 ]
0 1 0 | y z : [2/9 , 5/6 ]
0 1 1 | y z : [1 , 1 ]
0 0 0 | y : [0 , 0 ]
0 1 0 | y : [1 , 1 ]
0 0 0 | z : [0 , 0 ]
0 0 1 | z : [1 , 1 ]
Return a coherent version, using linear programming.
Return extreme points of the credal set conditional on event.
Returns: | The extreme points. |
---|---|
Return type: | Yields a tuple for each extreme point. |
Calculate lower expectation, using Algorithm 4 of Walley, Pelessoni, and Vicig (2004) [2]. The algorithm deals properly with zero probabilities.
Matrix representing the constraints of this lower prevision conditional on the given event.
Calculate the relevant items for calculating the natural extension conditional on an event.
This is part (a) (b) (c) of Algorithm 4 of Walley, Pelessoni, and Vicig (2004) [2]. Also see their Algorithm 2, which is a special case of Algorithm 4 but with event equal to the empty set.
Check avoiding sure loss by linear programming.
This is Algorithm 2 of Walley, Pelessoni, and Vicig (2004) [2].
Constrain the expectation of gamble to be at least lprev.
Parameters: |
---|
Constrain the expectation of gamble to be exactly prev.
Parameters: |
---|
The following examples presume:
>>> from improb.lowprev.lowpoly import LowPoly
>>> from improb.lowprev.lowprob import LowProb
>>> from improb.lowprev.prob import Prob
>>> from improb.decision.opt import OptLowPrevMax
>>> lpr = LowPoly(pspace=3, number_type='fraction')
>>> print "%.6f" % lpr.get_lower([1,2,3])
1.000000
>>> print "%.6f" % lpr.get_upper([1,2,3])
3.000000
>>> lpr.set_lower([1,2,3], 1.5)
>>> lpr.set_upper([1,2,3], 2.5)
>>> print(lpr.get_matrix())
H-representation
linearity 1 1
begin
6 4 rational
1 -1 -1 -1
0 1 0 0
0 0 1 0
0 0 0 1
0 -1/2 1/2 3/2
0 3/2 1/2 -1/2
end
minimize
0 0 0 0
>>> print(lpr.get_lower([1,2,3]))
3/2
>>> print(lpr.get_upper([1,2,3]))
5/2
>>> print('\n'.join(' '.join(str(x) for x in prob) for prob in sorted(lpr.get_credal_set())))
0 1/2 1/2
0 1 0
1/4 0 3/4
1/2 1/2 0
3/4 0 1/4
Another example:
>>> lpr = LowPoly(pspace=4, number_type='fraction')
>>> lpr.set_lower([4,2,1,0], 3)
>>> lpr.set_upper([4,1,2,0], 3)
>>> lpr.is_avoiding_sure_loss()
True
>>> lpr.is_coherent()
True
>>> lpr.is_linear()
False
>>> print(lpr.get_lower([1,0,0,0]))
1/2
>>> print(lpr.get_upper([1,0,0,0]))
3/4
>>> print(lpr)
0 1 2 3
4 1 2 0 | 0 1 2 3 : [ , 3]
4 2 1 0 | 0 1 2 3 : [3, ]
>>> opt = OptLowPrevMax(lpr)
>>> list(opt([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]))
[[1, 0, 0, 0], [0, 1, 0, 0]]
>>> list(opt([[0,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]))
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
Another example, involving zero probabilities (see Example 9 and 11 in [2]):
>>> pspace = PSpace(2, 2, 2, 2, 2)
>>> a1 = pspace.make_event((0,), (0, 1), (0, 1), (0, 1), (0, 1))
>>> a2 = pspace.make_event((0, 1), (0,), (0, 1), (0, 1), (0, 1))
>>> a3 = pspace.make_event((0, 1), (0, 1), (0,), (0, 1), (0, 1))
>>> a4 = pspace.make_event((0, 1), (0, 1), (0, 1), (0,), (0, 1))
>>> a5 = pspace.make_event((0, 1), (0, 1), (0, 1), (0, 1), (0,))
>>> lpr = LowPoly(pspace, number_type='fraction')
>>> lpr[a1, True] = ('0.6', '0.6')
>>> lpr[a1.complement() | a2, True] = ('0.4', '0.4')
>>> lpr[a2 | a3, True] = ('0.8', '0.8')
>>> lpr[a3 & a4, True] = ('0.3', '0.3')
>>> lpr[a4.complement() | a5, True] = ('0.5', '0.5')
>>> lpr[a2 | a5, True] = ('0.6', '0.6')
>>> lpr.get_lower(a3)
Fraction(2, 5)
>>> lpr.get_upper(a3)
Fraction(4, 5)
>>> lpr.get_lower(a4, event=a3)
Fraction(3, 8)
>>> lpr.get_upper(a4, event=a3)
Fraction(3, 4)
>>> lpr.get_lower((a1 & a2).complement(), event=(a1 & a2) | (a1.complement() & a2.complement()))
0
Another more complex example:
>>> lpr_s = LowPoly(pspace=3, number_type='fraction')
>>> lpr_s.set_lower([1,0,0], '0.4')
>>> lpr_s.set_upper([1,0,0], '0.5')
>>> lpr_s.set_lower([0,1,0], '0.3')
>>> lpr_s.set_upper([0,1,0], '0.4')
>>> lpr_s.set_lower([0,0,1], '0.2')
>>> lpr_s.set_upper([0,0,1], '0.2')
>>> lpr_s.is_coherent()
True
>>> print(lpr_s.get_lower([1,0,0]))
2/5
>>> print(lpr_s.get_upper([1,0,0]))
1/2
>>> print(lpr_s.get_lower([0,1,0]))
3/10
>>> print(lpr_s.get_upper([0,1,0]))
2/5
>>> print(lpr_s.get_lower([0,0,1]))
1/5
>>> print(lpr_s.get_upper([0,0,1]))
1/5
>>> print(lpr_s.get_lower([-7,5,20]))
2
>>> print(lpr_s.get_upper([-7,5,20]))
16/5
>>> lpr_t_s = [LowPoly(pspace=3, number_type='fraction') for i in xrange(3)]
>>> lpr_t_s[0].set_precise([1,0,0], '0.6')
>>> lpr_t_s[0].set_precise([0,1,0], '0.3')
>>> lpr_t_s[0].set_precise([0,0,1], '0.1')
>>> lpr_t_s[0].is_coherent()
True
>>> lpr_t_s[1].set_precise([1,0,0], '0.3')
>>> lpr_t_s[1].set_precise([0,1,0], '0.4')
>>> lpr_t_s[1].set_precise([0,0,1], '0.3')
>>> lpr_t_s[1].is_coherent()
True
>>> lpr_t_s[2].set_precise([1,0,0], '0.1')
>>> lpr_t_s[2].set_precise([0,1,0], '0.4')
>>> lpr_t_s[2].set_precise([0,0,1], '0.5')
>>> lpr_t_s[2].is_coherent()
True
>>> # a gamble which is a function of s and t; s comes as first
>>> # argument (in order to match lpr_t_s): gamble_t_s[s][t]
>>> gamble_t_s = [[1,0,0], [1,0,0], [1,0,0]] # event t=0
>>> # calculate its lower prevision by marginal extension
>>> print(lpr_s.get_lower([lpr_t.get_lower(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
19/50
>>> print(lpr_s.get_upper([lpr_t.get_upper(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
41/100
>>> gamble_t_s = [[0,1,0], [0,1,0], [0,1,0]] # event t=1
>>> print(lpr_s.get_lower([lpr_t.get_lower(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
7/20
>>> print(lpr_s.get_upper([lpr_t.get_upper(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
9/25
>>> gamble_t_s = [[0,0,1], [0,0,1], [0,0,1]] # event t=2
>>> print(lpr_s.get_lower([lpr_t.get_lower(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
6/25
>>> print(lpr_s.get_upper([lpr_t.get_upper(gamble_t)
... for lpr_t, gamble_t in zip(lpr_t_s, gamble_t_s)]))
13/50
>>> lpr = LowProb(pspace=2)
>>> lpr.set_lower([0,0], 0)
>>> lpr.set_lower([1,0], 0.3)
>>> lpr.set_lower([0,1], 0.2)
>>> lpr.set_lower([1,1], 1)
>>> print(lpr.mobius)
: 0.0
0 : 0.3
1 : 0.2
0 1 : 0.5
>>> lpr = LowPoly(pspace=4, number_type='fraction')
>>> lpr.set_precise([1,1,0,0], '0.6')
>>> lpr.set_precise([0,1,1,0], '0.7')
>>> print(lpr.get_lower([0,1,0,0])) # max(0.6+0.7-1,0)
3/10
>>> print(lpr.get_upper([0,1,0,0])) # min(0.6,0.7)
3/5
>>> lpr.is_linear()
True
>>> for vert in lpr.get_credal_set():
... print(" ".join("%.2f" % float(x) for x in vert))
0.30 0.30 0.40 0.00
0.00 0.60 0.10 0.30
This example incurs sure loss because the maximum of the sum of the gambles [1,2,3,0] and [3,2,1,0] is 4, however 2.5 + 2.5 is strictly larger than 4.
>>> lpr = LowPoly(pspace=4)
>>> lpr.set_lower([1,2,3,0], 2.5)
>>> lpr.set_lower([3,2,1,0], 2.5)
>>> lpr.is_avoiding_sure_loss()
False
A few simple examples:
>>> lpr = LowPoly(pspace='xyz')
>>> lpr.is_avoiding_sure_loss()
True
>>> lpr = LowPoly(pspace='xyz', lprob=['0.1', '0.2', '0.15'])
>>> lpr[{'x':1}, 'x'] = (1, None)
>>> lpr[{'x':0}, 'x'] = (0, None)
>>> lpr.is_avoiding_sure_loss()
True
See if we can handle zero probabilities:
>>> lpr = LowPoly(pspace='abcd', number_type='fraction')
>>> lpr[{'a': 1}, True] = (1, None)
>>> print(lpr)
a b c d
1 0 0 0 | a b c d : [1, ]
>>> lpr.is_avoiding_sure_loss()
True
Slightly more complicated:
>>> lpr = LowPoly(pspace='abcd', number_type='fraction')
>>> lpr[{'a': 1}, True] = (1, None)
>>> lpr[{'b': 1}, 'bcd'] = (2, None) # obviously incurs sure loss!
>>> print(lpr)
a b c d
1 0 0 0 | a b c d : [1, ]
0 1 0 0 | b c d : [2, ]
>>> lpr.is_avoiding_sure_loss()
False
And even slightly more complicated:
>>> lpr = LowPoly(pspace='abcd', number_type='fraction')
>>> lpr[{'a': 1}, True] = (1, None)
>>> lpr[{'b': 1}, 'bcd'] = ('2/3', None)
>>> lpr[{'c': 1}, 'bcd'] = ('2/3', None) # sum larger than one on this layer
>>> print(lpr)
a b c d
1 0 0 0 | a b c d : [1 , ]
0 0 1 0 | b c d : [2/3, ]
0 1 0 0 | b c d : [2/3, ]
>>> lpr.is_avoiding_sure_loss()
False
Another more complex example:
>>> lpr_s_t = LowPoly(pspace=9)
>>> lpr_s_t.set_lower([1,0,0,0,0,0,0,0,0], 0.500)
>>> lpr_s_t.set_upper([1,0,0,0,0,0,0,0,0], 0.666)
>>> lpr_s_t.set_lower([0,1,0,0,0,0,0,0,0], 0.222)
>>> lpr_s_t.set_upper([0,1,0,0,0,0,0,0,0], 0.272)
>>> lpr_s_t.set_lower([0,0,1,0,0,0,0,0,0], 0.125)
>>> lpr_s_t.set_upper([0,0,1,0,0,0,0,0,0], 0.181)
>>> lpr_s_t.set_lower([0,0,0,1,0,0,0,0,0], 0.222)
>>> lpr_s_t.set_upper([0,0,0,1,0,0,0,0,0], 0.333)
>>> lpr_s_t.set_lower([0,0,0,0,1,0,0,0,0], 0.363)
>>> lpr_s_t.set_upper([0,0,0,0,1,0,0,0,0], 0.444)
>>> lpr_s_t.set_lower([0,0,0,0,0,1,0,0,0], 0.250)
>>> lpr_s_t.set_upper([0,0,0,0,0,1,0,0,0], 0.363)
>>> lpr_s_t.set_lower([0,0,0,0,0,0,1,0,0], 0.111)
>>> lpr_s_t.set_upper([0,0,0,0,0,0,1,0,0], 0.166)
>>> lpr_s_t.set_lower([0,0,0,0,0,0,0,1,0], 0.333)
>>> lpr_s_t.set_upper([0,0,0,0,0,0,0,1,0], 0.363)
>>> lpr_s_t.set_lower([0,0,0,0,0,0,0,0,1], 0.454)
>>> lpr_s_t.set_upper([0,0,0,0,0,0,0,0,1], 0.625)
>>> lpr_s_t.is_avoiding_sure_loss()
False
>>> lpr = LowPoly(pspace=4)
>>> lpr.set_lower([1,2,3,0], 2.5)
>>> lpr.is_coherent()
True
>>> lpr.set_upper([2,4,6,0], 3) # coherence requires at least 5
>>> lpr.is_coherent()
False
>>> lpr = LowPoly(pspace=4)
>>> lpr.set_lower([1,2,3,0], 2.5)
>>> lpr.is_linear()
False
>>> lpr.set_upper([2,4,6,0], 5)
>>> lpr.is_linear()
True
Finding coherent lower and upper bounds for the oil wildcatter example in [1]:
>>> # lower previsions over s, given t
>>> lpr_s_t = [LowPoly(pspace=3),
... LowPoly(pspace=3),
... LowPoly(pspace=3)]
>>> # lower prevision over t
>>> lpr_t = LowPoly(pspace=3)
>>> lpr_s_t[0].set_lower([1,0,0], 0.5)
>>> lpr_s_t[0].set_upper([1,0,0], 0.666)
>>> lpr_s_t[0].set_lower([0,1,0], 0.222)
>>> lpr_s_t[0].set_upper([0,1,0], 0.272)
>>> lpr_s_t[0].set_lower([0,0,1], 0.125)
>>> lpr_s_t[0].set_upper([0,0,1], 0.181)
>>> lpr_s_t[0].is_coherent()
False
>>> print(float(lpr_s_t[0].get_lower([1,0,0]))) # not coherent!
0.547
>>> print(float(lpr_s_t[0].get_upper([1,0,0]))) # not coherent!
0.653
>>> print(float(lpr_s_t[0].get_lower([0,1,0])))
0.222
>>> print(float(lpr_s_t[0].get_upper([0,1,0])))
0.272
>>> print(float(lpr_s_t[0].get_lower([0,0,1])))
0.125
>>> print(float(lpr_s_t[0].get_upper([0,0,1])))
0.181
>>> lpr_s_t[1].set_lower([1,0,0], 0.222)
>>> lpr_s_t[1].set_upper([1,0,0], 0.333)
>>> lpr_s_t[1].set_lower([0,1,0], 0.363)
>>> lpr_s_t[1].set_upper([0,1,0], 0.444)
>>> lpr_s_t[1].set_lower([0,0,1], 0.250)
>>> lpr_s_t[1].set_upper([0,0,1], 0.363)
>>> lpr_s_t[1].is_coherent()
True
>>> print(float(lpr_s_t[1].get_lower([1,0,0])))
0.222
>>> print(float(lpr_s_t[1].get_upper([1,0,0])))
0.333
>>> print(float(lpr_s_t[1].get_lower([0,1,0])))
0.363
>>> print(float(lpr_s_t[1].get_upper([0,1,0])))
0.444
>>> print(float(lpr_s_t[1].get_lower([0,0,1])))
0.25
>>> print(float(lpr_s_t[1].get_upper([0,0,1])))
0.363
>>> lpr_s_t[2].set_lower([1,0,0], 0.111)
>>> lpr_s_t[2].set_upper([1,0,0], 0.166)
>>> lpr_s_t[2].set_lower([0,1,0], 0.333)
>>> lpr_s_t[2].set_upper([0,1,0], 0.363)
>>> lpr_s_t[2].set_lower([0,0,1], 0.454)
>>> lpr_s_t[2].set_upper([0,0,1], 0.625)
>>> lpr_s_t[2].is_coherent()
False
>>> print(float(lpr_s_t[2].get_lower([1,0,0])))
0.111
>>> print(float(lpr_s_t[2].get_upper([1,0,0])))
0.166
>>> print(float(lpr_s_t[2].get_lower([0,1,0])))
0.333
>>> print(float(lpr_s_t[2].get_upper([0,1,0])))
0.363
>>> print(float(lpr_s_t[2].get_lower([0,0,1]))) # not coherent!
0.471
>>> print(float(lpr_s_t[2].get_upper([0,0,1]))) # not coherent!
0.556
>>> lpr_t.set_lower([1,0,0], 0.181)
>>> lpr_t.set_upper([1,0,0], 0.222)
>>> lpr_t.set_lower([0,1,0], 0.333)
>>> lpr_t.set_upper([0,1,0], 0.363)
>>> lpr_t.set_lower([0,0,1], 0.444)
>>> lpr_t.set_upper([0,0,1], 0.454)
>>> lpr_t.is_coherent()
False
>>> print(float(lpr_t.get_lower([1,0,0]))) # not coherent!
0.183
>>> print(float(lpr_t.get_upper([1,0,0])))
0.222
>>> print(float(lpr_t.get_lower([0,1,0])))
0.333
>>> print(float(lpr_t.get_upper([0,1,0])))
0.363
>>> print(float(lpr_t.get_lower([0,0,1])))
0.444
>>> print(float(lpr_t.get_upper([0,0,1])))
0.454
>>> # now some calculations
>>> gamble_s = [-7, 5, 20]
>>> minus_gamble_s = [7, -5, -20]
>>> print(float(lpr_s_t[0].get_lower(gamble_s)))
-0.961
>>> print(float(lpr_s_t[0].get_lower(minus_gamble_s)))
-1.151
>>> print(float(lpr_s_t[1].get_lower(gamble_s)))
4.754
>>> print(float(lpr_s_t[1].get_lower(minus_gamble_s)))
-7.781
>>> print(float(lpr_s_t[2].get_lower(gamble_s)))
10.073
>>> print(float(lpr_s_t[2].get_lower(minus_gamble_s)))
-12.008
>>> # calculate its lower prevision by marginal extension
>>> # XXX this is a quick hackish way to set up the marginal extension
>>> # XXX see decision tree example for something more sane
>>> lpr = LowPoly(pspace=9)
>>> def get_lower(gamble_s_t):
... return lpr_t.get_lower([lpr_s.get_lower(gamble_s)
... for lpr_s, gamble_s
... in zip(lpr_s_t, gamble_s_t)])
>>> def get_upper(gamble_s_t):
... return lpr_t.get_upper([lpr_s.get_upper(gamble_s)
... for lpr_s, gamble_s
... in zip(lpr_s_t, gamble_s_t)])
>>> lpr.get_lower = get_lower
>>> lpr.get_upper = get_upper
>>> # a gamble which is a function of s and t; t comes as first
>>> # argument (in order to match lpr_s_t): gamble_s_t[t][s]
>>> gamble_s_t = [[-7,5,20], [-7,5,20], [-7,5,20]]
>>> # do the calculations
>>> print(float(lpr.get_lower(gamble_s_t)))
5.846906
>>> print(float(lpr.get_upper(gamble_s_t)))
8.486768
>>> # another gamble which is a function of s and t
>>> gamble_s_t = [[-7,5,20], [0,0,0], [0,0,0]]
>>> # calculate its lower prevision by marginal extension
>>> print(float(lpr.get_lower(gamble_s_t)))
-0.213342
>>> # another gamble which is a function of s and t
>>> gamble_s_t = [[7,-5,-20], [0,0,0], [0,0,0]]
>>> # calculate its lower prevision by marginal extension
>>> print(float(lpr.get_lower(gamble_s_t)))
-0.255522
>>> # another gamble which is a function of s and t
>>> gamble_s_t = [[-1,-1,-1], [-1,11,26], [-1,11,26]]
>>> # calculate its lower prevision by marginal extension
>>> print(float(lpr.get_lower(gamble_s_t)))
10.506248
>>> print(float(lpr.get_upper(gamble_s_t)))
12.995135
The next example is effectively the Monty Hall problem.
>>> lpr = LowPoly(pspace=4, number_type='fraction')
>>> lpr.set_lower([1, 1, 0, 0], '1/3')
>>> lpr.set_lower([0, 0, 1, 0], '1/3')
>>> lpr.set_lower([0, 0, 0, 1], '1/3')
>>> print(lpr.get_lower([1, 1, 0, 0], set([0, 3])))
0
>>> print(lpr.get_lower([0, 0, 1, 1], set([0, 3])))
1/2
Footnotes
[1] | Kikuti, D., Cozman, F., de Campos, C.: Partially ordered preferences in decision trees: Computing strategies with imprecision in probabilities. In: R. Brafman, U. Junker (eds.) IJCAI-05 Multidisciplinary Workshop on Advances in Preference Handling, pp. 118–123, 2005. |
[2] | (1, 2, 3, 4) Peter Walley, Renato Pelessoni, and Paolo Vicig. Journal of Statistical Planning and Inference, 126(1):119-151, November 2004. |