Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix/compatibility issues #17

Open
wants to merge 6 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 79 additions & 189 deletions negotiator.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ class NoProtocol(BaseProtocol):
def __init__(self, num_regions, num_discrete_action_levels) -> None:
self.stages = []
super().__init__(num_regions, num_discrete_action_levels)

def reset(self):
self.minimum_mitigation_rate_all_regions = np.zeros(self.num_regions)

def get_protocol_state(self):
protocol_state = {
"minimum_mitigation_rate_all_regions": self.minimum_mitigation_rate_all_regions
/ self.num_discrete_action_levels,
}
return protocol_state


class BilateralNegotiatorWithOnlyTariff(BaseProtocol):
Expand Down Expand Up @@ -1423,243 +1433,123 @@ class BasicClub(BaseProtocol):

"""

def __init__(self, rice):
def __init__(self, num_regions, num_discrete_action_levels):
"""
Defines necessary parameters for communication
with rice class

Args:
Rice: instance of RICE-N model
"""
self.rice = rice
self.stages = [
{
"function": self.proposal_step,
"numberActions": (
[self.rice.num_discrete_action_levels]
),
"action_space": [num_discrete_action_levels],
},
{
"function": self.evaluation_step,
"numberActions": [2] * self.rice.num_regions,
"action_space": [2] * num_regions,
},
]
self.num_negotiation_stages = len(self.stages)
super().__init__(num_regions, num_discrete_action_levels)

def reset(self):
"""
Add any negotiator specific values to global state
"""
self.minimum_mitigation_rate_all_regions = np.zeros(self.num_regions)
self.proposed_mitigation_rate = np.zeros(self.num_regions)
self.proposal_decisions = np.zeros((self.num_regions, self.num_regions))

for key in [
"proposed_mitigation_rate",
]:
self.rice.set_global_state(
key = key,
value = np.zeros(self.rice.num_regions),
timestep = self.rice.timestep,
)

def proposal_step(self, actions=None):
def get_protocol_state(self):
protocol_state = {
"stage": np.array([self.stage_idx]) / self.num_stages,
"proposed_mitigation_rate": self.proposed_mitigation_rate
/ self.num_discrete_action_levels,
"minimum_mitigation_rate_all_regions": self.minimum_mitigation_rate_all_regions
/ self.num_discrete_action_levels,
"proposal_decisions": self.proposal_decisions,
"received_proposal_decisions": self.proposal_decisions.T,
}
return protocol_state

def get_pub_priv_features(self):
public_features = ["stage", "proposed_mitigation_rate", "minimum_mitigation_rate_all_regions"]
private_features = [
# "proposal_decisions",
"received_proposal_decisions",
]
return public_features, private_features

def proposal_step(self, actions: dict):
"""
Update Proposal States and Observations using proposal actions
Update Stage to 1 - Evaluation
"""
assert self.rice.negotiation_on
assert self.rice.stage == 1

assert isinstance(actions, dict)
assert len(actions) == self.rice.num_regions

action_offset_index = len(
self.rice.savings_action_nvec
+ self.rice.mitigation_rate_action_nvec
+ self.rice.export_action_nvec
+ self.rice.import_actions_nvec
+ self.rice.tariff_actions_nvec
)
assert self.stage_idx == 0

#each country proposes a mitigation rate 0-num_discrete_action_levels (10)
proposed_mitigation_rate = [
actions[region_id][
action_offset_index
]
/ self.rice.num_discrete_action_levels
for region_id in range(self.rice.num_regions)
]

self.rice.set_global_state(
"proposed_mitigation_rate", np.array(proposed_mitigation_rate), self.rice.timestep
)

obs = self.rice.generate_observation()
rew = {region_id: 0.0 for region_id in range(self.rice.num_regions)}
done = {"__all__": 0}
info = {}
return obs, rew, done, info
self.proposed_mitigation_rate = np.array(
[actions[region_id] for region_id in range(self.num_regions)]
).squeeze()

def evaluation_step(self, actions=None):
def evaluation_step(self, actions: dict):
"""
Update minimum mitigation rates
"""
assert self.rice.negotiation_on

assert self.rice.stage == 2

assert isinstance(actions, dict)
assert len(actions) == self.rice.num_regions

action_offset_index = len(
self.rice.savings_action_nvec
+ self.rice.mitigation_rate_action_nvec
+ self.rice.export_action_nvec
+ self.rice.import_actions_nvec
+ self.rice.tariff_actions_nvec
+ self.rice.proposal_actions_nvec
)
num_evaluation_actions = len(self.stages[1]["numberActions"])
assert self.stage_idx == 1

proposal_decisions = np.array(
[
actions[region_id][
action_offset_index : action_offset_index + num_evaluation_actions
]
for region_id in range(self.rice.num_regions)
]
self.proposal_decisions = np.array(
[actions[region_id] for region_id in range(self.num_regions)]
)
# Force set the evaluation for own proposal to accept
for region_id in range(self.rice.num_regions):
proposal_decisions[region_id, region_id] = 1

#update global states
self.rice.set_global_state("proposal_decisions", proposal_decisions, self.rice.timestep)
for region_id in range(self.num_regions):
self.proposal_decisions[region_id, region_id] = 1

proposed_mitigation_rates = np.array([self.rice.global_state["proposed_mitigation_rate"]["value"][
self.rice.timestep, j
] for j in range(self.rice.num_regions)])

for region_id in range(self.rice.num_regions):

result_mitigation = proposed_mitigation_rates * proposal_decisions[region_id, :]
self.rice.global_state["minimum_mitigation_rate_all_regions"]["value"][
self.rice.timestep, region_id
] = max(
result_mitigation
)
obs = self.rice.generate_observation()
rew = {region_id: 0.0 for region_id in range(self.rice.num_regions)}
done = {"__all__": 0}
info = {}
return obs, rew, done, info
mmrar = (self.proposed_mitigation_rate * self.proposal_decisions).max(axis=1)
self.minimum_mitigation_rate_all_regions = mmrar

def generate_action_mask(self):
def get_partial_action_mask(self):
"""
Generate action masks.
"""
mask_dict = {region_id: None for region_id in range(self.rice.num_regions)}
for region_id in range(self.rice.num_regions):
mask = self.rice.default_agent_action_mask.copy()
if self.rice.negotiation_on:

#mask mitigation as per own club
minimum_mitigation_rate = int(
round(
self.rice.global_state["minimum_mitigation_rate_all_regions"][
"value"
][self.rice.timestep, region_id]
* self.rice.num_discrete_action_levels
)
)
mitigation_mask = np.array(
[0 for _ in range(minimum_mitigation_rate)]
+ [
1
for _ in range(
self.rice.num_discrete_action_levels
- minimum_mitigation_rate
)
]
)
mask_start = sum(self.rice.savings_action_nvec)
mask_end = mask_start + sum(self.rice.mitigation_rate_action_nvec)
mask[mask_start:mask_end] = mitigation_mask

# tariff masks
tariff_masks = []
for other_region_id in range(self.rice.num_regions):

other_region_mitigation_rate = int(round(self.rice.global_state["minimum_mitigation_rate_all_regions"]["value"][self.rice.timestep, other_region_id]\
* self.rice.num_discrete_action_levels))

# if other region is self or self not in bilateral negotiation
if (other_region_id == region_id):

# make no change to tariff policy
regional_tariff_mask = np.array(
[1 for _ in range(self.rice.num_discrete_action_levels)]
)

# if other region's mitigation rate less than yours
elif other_region_mitigation_rate < minimum_mitigation_rate:

# tariff the 1-mitigation rate
region_tariff_rate = int(
round(
self.rice.num_discrete_action_levels
- self.rice.global_state[
"minimum_mitigation_rate_all_regions"
]["value"][self.rice.timestep, other_region_id]
)
)
action_mask_dict = defaultdict(dict)
for region_id in range(self.num_regions):
minimum_mitigation_rate = int(self.minimum_mitigation_rate_all_regions[region_id])
mitigation_mask = [0] * int(minimum_mitigation_rate) + [1] * int(
self.num_discrete_action_levels - minimum_mitigation_rate
)

regional_tariff_mask = np.array(
[0 for _ in range(region_tariff_rate)]
+ [
1
for _ in range(
self.rice.num_discrete_action_levels
- region_tariff_rate
)
]
)
# tariff masks
tariff_mask = []
for other_region_id in range(self.num_regions):
other_region_mitigation_rate = int(self.minimum_mitigation_rate_all_regions[other_region_id])

# if other regions mitigation >= your own bonus
else:
# set tarrif cap
region_tariff_rate = int(
round(
self.rice.num_discrete_action_levels
- self.rice.global_state[
"minimum_mitigation_rate_all_regions"
]["value"][self.rice.timestep, other_region_id]
)
)
# if other region is self or self not in bilateral negotiation
if (other_region_id == region_id):
# make no change to tariff policy
regional_tariff_mask = [1] * self.num_discrete_action_levels

regional_tariff_mask = np.array(
[1 for _ in range(region_tariff_rate)]
+ [
0
for _ in range(
self.rice.num_discrete_action_levels
- region_tariff_rate
)
]
)
tariff_masks.append(regional_tariff_mask)
# if other region's mitigation rate less than yours
elif other_region_mitigation_rate < minimum_mitigation_rate:
# tariff the 1-mitigation rate
region_tariff_rate = self.num_discrete_action_levels - other_region_mitigation_rate
regional_tariff_mask = [0] * region_tariff_rate + [1] * other_region_mitigation_rate

mask_start_tariff = sum(
self.rice.savings_action_nvec
+ self.rice.mitigation_rate_action_nvec
+ self.rice.export_action_nvec
+ self.rice.import_actions_nvec
)
# if other regions mitigation >= your own bonus
else:
# set tarrif cap
region_tariff_rate = self.num_discrete_action_levels - other_region_mitigation_rate
regional_tariff_mask = [1] * region_tariff_rate + [0] * other_region_mitigation_rate

mask_end_tariff = mask_start_tariff + sum(self.rice.tariff_actions_nvec)
mask[mask_start_tariff:mask_end_tariff] = np.concatenate(tariff_masks)
tariff_mask.extend(regional_tariff_mask)

mask_dict[region_id] = mask
action_mask_dict[region_id]["tariff"] = tariff_mask
action_mask_dict[region_id]["mitigation"] = mitigation_mask

return mask_dict
return action_mask_dict


class BilateralNegotiator(BaseProtocol):
Expand Down
4 changes: 2 additions & 2 deletions rice.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,9 @@ def generate_observation(self) -> dict:
"damages_all_regions",
"abatement_cost_all_regions",
"production_all_regions",
"utility_all_regions",
# "utility_all_regions",
"social_welfare_all_regions",
"reward_all_regions",
# "reward_all_regions",
]

# Features concerning two regions
Expand Down
Loading