44
55
66def solve_contract () -> float :
7- # --- Inputs ---
7+ """Solve for high-state consumption in a two-state stochastic contract.
8+
9+ Uses bisection to match a target lifetime utility under log preferences
10+ with a participation (exit) constraint in the high-income state.
11+ """
812 delta = 0.95
9- prob = 0.5 # equal probability for the two income states
13+ prob = 0.5
1014 c_low = 0.95
11- V0_target = 3.0
15+ v0_target = 3.0
1216
13- # Autarky utilities (if consumption equals income)
14- V_aut_high = math .log (1.1 ) / (1 - delta )
17+ v_aut_high = math .log (1.1 ) / (1.0 - delta )
1518
16- # Expected lifetime utility under the contract (given c_high)
1719 def expected_value (c_high : float ) -> float :
1820 if c_high <= 0 :
1921 return - math .inf
20- exp_u = prob * math .log (c_low ) + prob * math .log (c_high )
21- return exp_u / (1 - delta )
22+ eu = prob * math .log (c_low ) + prob * math .log (c_high )
23+ return eu / (1.0 - delta )
2224
23- # Participation / exit constraint in the high-income state:
24- # log(c_high)/(1-delta) >= log(1.1)/(1-delta) => c_high >= 1.1
2525 def exit_constraint (c_high : float ) -> bool :
2626 return c_high >= 1.1
2727
28- # Solve expected_value(c_high) = V0_target via bisection on (0, 10)
2928 tol = 1e-8
30- low , high = 1e-8 , 10.0
29+ lo , hi = 1e-8 , 10.0
3130
32- # Bracketing check (monotone in c_high)
33- if expected_value (low ) > V0_target :
34- raise ValueError ("Target too low for the chosen lower bound." )
35- if expected_value (high ) < V0_target :
36- raise ValueError ("Target too high for the chosen upper bound." )
31+ if expected_value (lo ) > v0_target :
32+ raise ValueError ("Target utility too low for lower bound." )
33+ if expected_value (hi ) < v0_target :
34+ raise ValueError ("Target utility too high for upper bound." )
3735
38- while high - low > tol :
39- mid = (low + high ) / 2
40- val = expected_value (mid )
41- if val < V0_target :
42- low = mid
36+ while hi - lo > tol :
37+ mid = 0.5 * (lo + hi )
38+ if expected_value (mid ) < v0_target :
39+ lo = mid
4340 else :
44- high = mid
45-
46- solution = (low + high ) / 2
41+ hi = mid
4742
48- # Enforce exit constraint if needed
49- if not exit_constraint (solution ):
50- print ("Exit constraint not satisfied by the utility-matching solution." )
51- print ("Raising c_high to the minimum feasible value: 1.100000" )
52- solution = max (solution , 1.1 )
53- else :
54- print ("Solution satisfies both the target utility and the exit constraint." )
43+ sol = 0.5 * (lo + hi )
44+ if not exit_constraint (sol ):
45+ sol = 1.1
5546
56- print (f"c_high (income=1.1): { solution :.6f} " )
57- print (f"Contract lifetime utility: { expected_value (solution ):.6f} " )
58- print (
59- f"High-state lifetime utility: { math .log (solution )/ (1 - delta ):.6f} "
60- f"(autarky minimum: { V_aut_high :.6f} )"
61- )
62- return float (solution )
47+ return float (sol )
6348
6449
6550if __name__ == "__main__" :
66- solve_contract ()
51+ print ( solve_contract () )
0 commit comments