101 lines
3 KiB
Python
101 lines
3 KiB
Python
|
"""
|
|||
|
fish.py
|
|||
|
~~~~~~~
|
|||
|
|
|||
|
This module solves the fish homework problem.
|
|||
|
|
|||
|
Run with "python fish.py"
|
|||
|
|
|||
|
Description:
|
|||
|
|
|||
|
Every year (for 3 years) we decide whether to fish in a lake or not.
|
|||
|
If we fish, the population of fish in the lake remains the same.
|
|||
|
If we don’t fish, the population of fish in the lake doubles.
|
|||
|
Years of experience tell us that our profit is exactly 70% of the
|
|||
|
number of fish in the lake if we fish.
|
|||
|
If there are 10 fish in the lake, we make $7.
|
|||
|
The interest rate is 25%
|
|||
|
We need a contingency plan: no matter what situation we find
|
|||
|
ourselves in, we need to have an optimal strategy.
|
|||
|
We could try every strategy, but that quickly gets out of control:
|
|||
|
there are too many possibilities!
|
|||
|
|
|||
|
Output:
|
|||
|
|
|||
|
{0: {10: {'fish': False, 'value': 32.25600000000001}},
|
|||
|
1: {10: {'fish': False, 'value': 20.160000000000004},
|
|||
|
20: {'fish': False, 'value': 40.32000000000001}},
|
|||
|
2: {10: {'fish': True, 'value': 12.600000000000001},
|
|||
|
20: {'fish': True, 'value': 25.200000000000003},
|
|||
|
40: {'fish': True, 'value': 50.400000000000006}},
|
|||
|
3: {10: {'fish': True, 'value': 7.0},
|
|||
|
20: {'fish': True, 'value': 14.0},
|
|||
|
40: {'fish': True, 'value': 28.0},
|
|||
|
80: {'fish': True, 'value': 56.0}},
|
|||
|
4: {10: {'value': 0},
|
|||
|
20: {'value': 0},
|
|||
|
40: {'value': 0},
|
|||
|
80: {'value': 0},
|
|||
|
160: {'value': 0}}}
|
|||
|
Optimal strategy: do not fish -> do not fish -> fish -> fish
|
|||
|
"""
|
|||
|
|
|||
|
from copy import deepcopy
|
|||
|
from pprint import pprint
|
|||
|
|
|||
|
|
|||
|
# Problem parameters
|
|||
|
initial_population = 10
|
|||
|
growth_factor = 2
|
|||
|
profit_rate = 0.7
|
|||
|
interest_rate = 0.25
|
|||
|
final_value = 0
|
|||
|
n_periods = 4
|
|||
|
|
|||
|
|
|||
|
# Initialize data structures to keep track of calculations
|
|||
|
tree = {
|
|||
|
0: {
|
|||
|
initial_population: {},
|
|||
|
},
|
|||
|
}
|
|||
|
max_population = initial_population
|
|||
|
|
|||
|
|
|||
|
# Construct the tree by forward calculation
|
|||
|
for i in range(n_periods):
|
|||
|
tree[i+1] = deepcopy(tree[i])
|
|||
|
max_population *= growth_factor
|
|||
|
tree[i+1][max_population] = {}
|
|||
|
|
|||
|
|
|||
|
# Set the values for all nodes in the last period to 0
|
|||
|
for key in tree[n_periods].keys():
|
|||
|
tree[n_periods][key]['value'] = 0
|
|||
|
|
|||
|
|
|||
|
# Value the tree by backward induction
|
|||
|
for i in reversed(range(n_periods)):
|
|||
|
for key in tree[i].keys():
|
|||
|
fish = profit_rate * key + (1 / (1 + interest_rate)) * tree[i+1][key]['value']
|
|||
|
no_fish = (1 / (1 + interest_rate)) * tree[i+1][key * growth_factor]['value']
|
|||
|
tree[i][key]['value'] = max(fish, no_fish)
|
|||
|
if fish > no_fish:
|
|||
|
tree[i][key]['fish'] = True
|
|||
|
else:
|
|||
|
tree[i][key]['fish'] = False
|
|||
|
|
|||
|
|
|||
|
# Print the decision rule
|
|||
|
result = []
|
|||
|
optimal_population = initial_population
|
|||
|
for i in range(n_periods):
|
|||
|
if tree[i][optimal_population]['fish']:
|
|||
|
result.append('fish')
|
|||
|
else:
|
|||
|
result.append('do not fish')
|
|||
|
optimal_population *= growth_factor
|
|||
|
|
|||
|
pprint(tree)
|
|||
|
print('Optimal strategy: ' + ' -> '.join(result))
|