adding ai_economist for modding
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) 2021, salesforce.com, inc.
|
||||
# All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# For full license text, see the LICENSE file in the repo root
|
||||
# or https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
def dict_merge(dct, merge_dct):
|
||||
"""Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
|
||||
updating only top-level keys, dict_merge recurses down into dicts nested
|
||||
to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
|
||||
``dct``.
|
||||
:param dct: dict onto which the merge is executed
|
||||
:param merge_dct: dct merged into dct
|
||||
:return: None
|
||||
"""
|
||||
for k, v in merge_dct.items():
|
||||
# dct does not have k yet. Add it with value v.
|
||||
if (k not in dct) and (not isinstance(dct, list)):
|
||||
dct[k] = v
|
||||
else:
|
||||
# dct[k] and merge_dict[k] are both dictionaries. Recurse.
|
||||
if isinstance(dct[k], (dict, list)) and isinstance(v, dict):
|
||||
dict_merge(dct[k], merge_dct[k])
|
||||
else:
|
||||
# dct[k] and merge_dict[k] are both tuples or lists.
|
||||
if isinstance(dct[k], (tuple, list)) and isinstance(v, (tuple, list)):
|
||||
# They don't match. Overwrite with v.
|
||||
if len(dct[k]) != len(v):
|
||||
dct[k] = v
|
||||
else:
|
||||
for i, (d_val, v_val) in enumerate(zip(dct[k], v)):
|
||||
if isinstance(d_val, dict) and isinstance(v_val, dict):
|
||||
dict_merge(d_val, v_val)
|
||||
else:
|
||||
dct[k][i] = v_val
|
||||
else:
|
||||
dct[k] = v
|
||||
|
||||
|
||||
def min_max_consumer_budget_delta(hparams_dict):
|
||||
# largest single round changes
|
||||
max_wage = hparams_dict["agents"]["max_possible_wage"]
|
||||
max_hours = hparams_dict["agents"]["max_possible_hours_worked"]
|
||||
max_price = hparams_dict["agents"]["max_possible_price"]
|
||||
max_singlefirm_consumption = hparams_dict["agents"]["max_possible_consumption"]
|
||||
num_firms = hparams_dict["agents"]["num_firms"]
|
||||
|
||||
min_budget = (
|
||||
-max_singlefirm_consumption * max_price * num_firms
|
||||
) # negative budget from consuming only
|
||||
max_budget = max_hours * max_wage * num_firms # positive budget from only working
|
||||
return min_budget, max_budget
|
||||
|
||||
|
||||
def min_max_stock_delta(hparams_dict):
|
||||
# for now, assuming 1.0 capital
|
||||
max_hours = hparams_dict["agents"]["max_possible_hours_worked"]
|
||||
max_singlefirm_consumption = hparams_dict["agents"]["max_possible_consumption"]
|
||||
alpha = hparams_dict["world"]["production_alpha"]
|
||||
if isinstance(alpha, str):
|
||||
alpha = 0.8
|
||||
num_consumers = hparams_dict["agents"]["num_consumers"]
|
||||
max_delta = (max_hours * num_consumers) ** alpha
|
||||
min_delta = -max_singlefirm_consumption * num_consumers
|
||||
return min_delta, max_delta
|
||||
|
||||
|
||||
def min_max_firm_budget(hparams_dict):
|
||||
max_wage = hparams_dict["agents"]["max_possible_wage"]
|
||||
max_hours = hparams_dict["agents"]["max_possible_hours_worked"]
|
||||
max_singlefirm_consumption = hparams_dict["agents"]["max_possible_consumption"]
|
||||
num_consumers = hparams_dict["agents"]["num_consumers"]
|
||||
max_price = hparams_dict["agents"]["max_possible_price"]
|
||||
max_delta = max_singlefirm_consumption * max_price * num_consumers
|
||||
min_delta = -max_hours * max_wage * num_consumers
|
||||
return min_delta, max_delta
|
||||
|
||||
|
||||
def expand_to_digit_form(x, dims_to_expand, max_digits):
|
||||
# first split x up
|
||||
requires_grad = (
|
||||
x.requires_grad
|
||||
) # don't want to backprop through these ops, but do want
|
||||
# gradients if x had them
|
||||
with torch.no_grad():
|
||||
tensor_pieces = []
|
||||
expanded_digit_shape = x.shape[:-1] + (max_digits,)
|
||||
for i in range(x.shape[-1]):
|
||||
if i not in dims_to_expand:
|
||||
tensor_pieces.append(x[..., i : i + 1])
|
||||
else:
|
||||
digit_entries = torch.zeros(expanded_digit_shape, device=x.device)
|
||||
for j in range(max_digits):
|
||||
digit_entries[..., j] = (x[..., i] % (10 ** (j + 1))) / (
|
||||
10 ** (j + 1)
|
||||
)
|
||||
tensor_pieces.append(digit_entries)
|
||||
|
||||
output = torch.cat(tensor_pieces, dim=-1)
|
||||
output.requires_grad_(requires_grad)
|
||||
return output
|
||||
|
||||
|
||||
def size_after_digit_expansion(existing_size, dims_to_expand, max_digits):
|
||||
num_expanded = len(dims_to_expand)
|
||||
# num non expanded digits, + all the expanded ones
|
||||
return (existing_size - num_expanded) + (max_digits * num_expanded)
|
||||
Reference in New Issue
Block a user