Hours Worth Working

labour-leisure choice · tax bands · benefit withdrawal · exhaustive search

Ruth decides how many whole hours h to work each week, from 0 to 60. She has 80 hours a week for work and leisure together, so her leisure is 80 - h hours. Each hour pays wage euros, so her gross earnings are wage * h. What she can spend, her consumption c, is her earnings minus income tax plus a benefit:

  • Income tax is charged in bands. tax_bands is a list of pairs (threshold, rate) with increasing thresholds, the first one 0. Each rate applies to the part of the week's earnings between its threshold and the next one (the last band has no upper end). With [(0, 0.0), (300, 0.25)] the first 300 euros are tax-free and every euro above 300 is taxed at 25 %.
  • The benefit pays benefit euros a week, reduced by taper euros for every euro earned, and never below 0: she receives max(0, benefit - taper * earnings). The benefit is not taxed.

Ruth's utility is Cobb-Douglas in consumption and leisure, with a the weight on consumption (0 < a < 1):

U = c^{a} \cdot (80 - h)^{1 - a}

Write work_week(wage, a, tax_bands, benefit, taper) that returns a tuple (h, c): the hours that give the highest utility, and her consumption at those hours. Let U^* be the highest utility over all choices; two choices this close count as equally good, so return the fewest hours whose utility is at least U^* \cdot (1 - 10^{-9}).

Collect the 61 utilities in a list utilities and press Run with plot(utilities) to see their shape. With a fast benefit withdrawal (try wage = 12, a = 0.55, tax_bands = [(0, 0.1)], benefit = 300, taper = 1.0) utility first falls as hours rise, and climbs again only once the benefit is used up.

Examples

Input:  wage = 15, a = 0.5, tax_bands = [(0, 0.2)], benefit = 0, taper = 0
Output: (40, 480.0)
Explanation: she keeps 12 euros an hour, U = sqrt(12h * (80 - h)), highest at h = 40.

Input:  wage = 10, a = 0.5, tax_bands = [(0, 0.0), (300, 0.25)], benefit = 250, taper = 0.7
Output: (0, 250.0)
Explanation: while the benefit lasts, each hour adds 10 euros of pay but takes away 7 of
benefit. Not working (U = sqrt(250 * 80) = 141.42) beats every positive number of hours.

Input:  wage = 10, a = 0.5, tax_bands = [(0, 0.0), (300, 0.25)], benefit = 250, taper = 0
Output: (27, 520.0)
Explanation: 27 hours (520 * 53) and 28 hours (530 * 52) give the same utility; take fewer.

Constraints

  • consumption is compared with a tolerance of 1e-6
  • the tests have no near-ties: every choice's utility is either within 1e-12 of U^* (relative) or more than 1e-7 below it

Goals

  • Turn hours of work into spending money through a banded income tax and a tapered benefit
  • Choose the hours that maximise a Cobb-Douglas utility of consumption and leisure
  • See how withdrawing a benefit as earnings rise can make working fewer hours, or none, the best choice
Starting Python…